void JigsawPuzzleRenderer::CreatePuzzlePieceGeometry()
{
    // Create the geometry outline for the jigsaw puzzle piece.
    ComPtr<ID2D1PathGeometry> path;
    ComPtr<ID2D1GeometrySink> sink;

    DX::ThrowIfFailed(m_deviceResources->GetD2DFactory()->CreatePathGeometry(&path));
    DX::ThrowIfFailed(path->Open(&sink));

    // The following math calculates the information needed to determine where the arcs for the puzzle piece connector begin and end.
    // The inner radius is the radius of the arc that defines the stem of the connector. The outer radius is the radius of the arc
    // that defines the connector.

    float edgeLength = Constants::PuzzlePieceSize;
    float innerRadius = Constants::PuzzlePieceConnectorInnerRadius;
    float outerRadius = Constants::PuzzlePieceConnectorOuterRadius;
    float stemPosition = (edgeLength / 2.0f) - (innerRadius * 2.0f);
    float connectorParallelOffset = (2.0f * pow(innerRadius, 2.0f)) / (innerRadius + outerRadius);
    float connectorPerpendicularOffset = sqrt(pow(innerRadius, 2.0f) - pow(connectorParallelOffset, 2.0f)) + innerRadius;

    sink->BeginFigure(D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED);
    sink->AddLine(D2D1::Point2F(edgeLength, 0));
    sink->AddLine(D2D1::Point2F(edgeLength, stemPosition));
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(edgeLength - connectorPerpendicularOffset, stemPosition + connectorParallelOffset),
            D2D1::SizeF(innerRadius, innerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_CLOCKWISE,
            D2D1_ARC_SIZE_SMALL
            )
        );
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(edgeLength - connectorPerpendicularOffset, edgeLength - stemPosition - connectorParallelOffset),
            D2D1::SizeF(outerRadius, outerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
            D2D1_ARC_SIZE_LARGE
            )
        );
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(edgeLength, edgeLength - stemPosition),
            D2D1::SizeF(innerRadius, innerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_CLOCKWISE,
            D2D1_ARC_SIZE_SMALL
            )
        );
    sink->AddLine(D2D1::Point2F(edgeLength, edgeLength));
    sink->AddLine(D2D1::Point2F(edgeLength - stemPosition, edgeLength));
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(edgeLength - stemPosition - connectorParallelOffset, edgeLength + connectorPerpendicularOffset),
            D2D1::SizeF(innerRadius, innerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
            D2D1_ARC_SIZE_SMALL
            )
        );
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(stemPosition + connectorParallelOffset, edgeLength + connectorPerpendicularOffset),
            D2D1::SizeF(outerRadius, outerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_CLOCKWISE,
            D2D1_ARC_SIZE_LARGE
            )
        );
    sink->AddArc(
        D2D1::ArcSegment(
            D2D1::Point2F(stemPosition, edgeLength),
            D2D1::SizeF(innerRadius, innerRadius),
            0.0f,
            D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
            D2D1_ARC_SIZE_SMALL
            )
        );
    sink->AddLine(D2D1::Point2F(0, edgeLength));
    sink->EndFigure(D2D1_FIGURE_END_CLOSED);

    DX::ThrowIfFailed(sink->Close());
    m_geometry = path;
}