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; }