src/editmodes/circleMode.cpp

changeset 1390
3eace926af7f
parent 1344
d28f6ff1b1f0
child 1392
0541d9b21968
equal deleted inserted replaced
1389:3fb8ad4d27b1 1390:3eace926af7f
58 } 58 }
59 59
60 return 0.0; 60 return 0.0;
61 } 61 }
62 62
63 static Matrix shearMatrixForPlane(Canvas* renderer)
64 {
65 const Plane& plane = renderer->drawPlane();
66 Axis localx, localy;
67 renderer->getRelativeAxes(localx, localy);
68 Axis localz = renderer->getRelativeZ();
69 Matrix shearMatrix = Matrix::identity;
70 Vertex normalAsVertex = Vertex::fromVector(plane.normal);
71
72 // Compute shear matrix values. The (Y, X) cell means a slope for Y in regard to X.
73 // If x grows by 2, y grows by 2 times this value. In the circle primitives,
74 // depth is Y, but in the orthogonal view, depth is Z. So Y and Z must be swapped.
75 if (not qFuzzyCompare(normalAsVertex[localz], 0.0))
76 {
77 // The slope of the vector is 90° offset from the normal vector. So Y/X slope is
78 // -X/Y from the normal vector.
79 shearMatrix(Y, X) = -normalAsVertex[localx] / normalAsVertex[localz];
80 shearMatrix(Y, Z) = -normalAsVertex[localy] / normalAsVertex[localz];
81 }
82
83 return shearMatrix;
84 }
63 85
64 void CircleMode::endDraw() 86 void CircleMode::endDraw()
65 { 87 {
66 Model model {m_documents}; 88 Model model {m_documents};
67 PrimitiveModel primitiveModel; 89 PrimitiveModel primitiveModel;
70 primitiveModel.ringNumber = 0; 92 primitiveModel.ringNumber = 0;
71 double dist0 (getCircleDrawDist (0)); 93 double dist0 (getCircleDrawDist (0));
72 double dist1 (getCircleDrawDist (1)); 94 double dist1 (getCircleDrawDist (1));
73 LDDocument* primitiveFile; 95 LDDocument* primitiveFile;
74 Matrix transform; 96 Matrix transform;
97
75 bool circleOrDisc = false; 98 bool circleOrDisc = false;
76 99
77 if (dist1 < dist0) 100 if (dist1 < dist0)
78 qSwap(dist0, dist1); 101 qSwap(dist0, dist1);
79 102
80 if (dist0 == dist1) 103 if (qFuzzyCompare(dist0, dist1))
81 { 104 {
82 // If the radii are the same, there's no ring space to fill. Use a circle. 105 // Special case: radii are the same, there's no area. Use a circle.
83 primitiveModel.type = PrimitiveModel::Circle; 106 primitiveModel.type = PrimitiveModel::Circle;
84 primitiveFile = primitives()->getPrimitive(primitiveModel); 107 primitiveFile = primitives()->getPrimitive(primitiveModel);
85 transform = Matrix::fromRotationMatrix(renderer()->currentCamera().transformationMatrix(dist0)); 108 // transform = shearMatrixForPlane(renderer());
109 transform = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(1));
110 transform *= Matrix::scaleMatrix(dist0);
86 circleOrDisc = true; 111 circleOrDisc = true;
87 } 112 }
88 else if (dist0 == 0 or dist1 == 0) 113 else if (qFuzzyCompare(dist0, 0) or qFuzzyCompare(dist1, 0))
89 { 114 {
90 // If either radii is 0, use a disc. 115 // Special case #2: one radius is 0, so use a disc.
91 primitiveModel.type = PrimitiveModel::Disc; 116 primitiveModel.type = PrimitiveModel::Disc;
92 primitiveFile = primitives()->getPrimitive(primitiveModel); 117 primitiveFile = primitives()->getPrimitive(primitiveModel);
93 transform = Matrix::fromRotationMatrix(renderer()->currentCamera().transformationMatrix((dist0 != 0) ? dist0 : dist1)); 118 //transform = shearMatrixForPlane(renderer());
119 transform = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(1));
120 transform *= Matrix::scaleMatrix(max(dist0, dist1));
94 circleOrDisc = true; 121 circleOrDisc = true;
95 } 122 }
96 else if (g_RingFinder.findRings(dist0, dist1)) 123 else if (g_RingFinder.findRings(dist0, dist1)) // Consult the ring finder now
97 { 124 {
98 // The ring finder found a solution, use that. Add the component rings to the file. 125 // The ring finder found a solution, use that. Add the component rings to the file.
99 primitiveModel.type = PrimitiveModel::Ring; 126 primitiveModel.type = PrimitiveModel::Ring;
100 127
101 for (const RingFinder::Component& component : g_RingFinder.bestSolution()->getComponents()) 128 for (const RingFinder::Component& component : g_RingFinder.bestSolution()->getComponents())
102 { 129 {
103 primitiveModel.ringNumber = component.num; 130 primitiveModel.ringNumber = component.num;
104 primitiveFile = primitives()->getPrimitive(primitiveModel); 131 primitiveFile = primitives()->getPrimitive(primitiveModel);
105 Matrix matrix = Matrix::fromRotationMatrix(renderer()->currentCamera().transformationMatrix(component.scale)); 132 Matrix matrix = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(component.scale));
133 // matrix = shearMatrixForPlane(renderer()) * matrix;
106 model.emplace<LDSubfileReference>(primitiveFile->name(), matrix, m_drawedVerts.first()); 134 model.emplace<LDSubfileReference>(primitiveFile->name(), matrix, m_drawedVerts.first());
107 } 135 }
108 } 136 }
109 else 137 else
110 { 138 {
116 double y0 = m_drawedVerts[0][localy]; 144 double y0 = m_drawedVerts[0][localy];
117 145
118 Vertex templ; 146 Vertex templ;
119 templ.setCoordinate(localx, x0); 147 templ.setCoordinate(localx, x0);
120 templ.setCoordinate(localy, y0); 148 templ.setCoordinate(localy, y0);
121 templ.setCoordinate(localz, renderer()->getDepthValue());
122 149
123 // Calculate circle coords 150 // Calculate circle coords
124 QVector<QLineF> c0 = makeCircle(primitiveModel.segments, primitiveModel.divisions, dist0); 151 QVector<QLineF> c0 = makeCircle(primitiveModel.segments, primitiveModel.divisions, dist0);
125 QVector<QLineF> c1 = makeCircle(primitiveModel.segments, primitiveModel.divisions, dist1); 152 QVector<QLineF> c1 = makeCircle(primitiveModel.segments, primitiveModel.divisions, dist1);
126 153
139 166
140 // Ensure the quads always are BFC-front towards the camera 167 // Ensure the quads always are BFC-front towards the camera
141 if (static_cast<int>(renderer()->camera()) % 3 <= 0) 168 if (static_cast<int>(renderer()->camera()) % 3 <= 0)
142 qSwap(v1, v3); 169 qSwap(v1, v3);
143 170
171 // Project the vertices onto the draw plane.
172 for (Vertex* vertex : {&v0, &v1, &v2, &v3})
173 *vertex = projectToDrawPlane(*vertex);
174
144 LDQuadrilateral* quad = model.emplace<LDQuadrilateral>(v0, v1, v2, v3); 175 LDQuadrilateral* quad = model.emplace<LDQuadrilateral>(v0, v1, v2, v3);
145 quad->setColor(MainColor); 176 quad->setColor(MainColor);
146 } 177 }
147 } 178 }
148 179
149 if (circleOrDisc and primitiveFile) 180 if (circleOrDisc and primitiveFile)
181 {
150 model.emplace<LDSubfileReference>(primitiveFile->name(), transform, m_drawedVerts.first()); 182 model.emplace<LDSubfileReference>(primitiveFile->name(), transform, m_drawedVerts.first());
183 }
151 184
152 finishDraw (model); 185 finishDraw (model);
153 } 186 }
154 187
155 /* 188 /*

mercurial