src/editmodes/circleMode.cc

changeset 866
4951b737f8cb
parent 865
6d68840fcb26
child 869
7184f3bae695
equal deleted inserted replaced
865:6d68840fcb26 866:4951b737f8cb
70 } 70 }
71 71
72 void CircleMode::buildCircle() 72 void CircleMode::buildCircle()
73 { 73 {
74 LDObjectList objs; 74 LDObjectList objs;
75 const int segs (g_win->ringToolHiRes() ? HighResolution : LowResolution); 75 const int segments (g_win->ringToolSegments());
76 const int divs (segs); // TODO: make customizable 76 const int divisions (g_win->ringToolHiRes() ? HighResolution : LowResolution);
77 double dist0 (getCircleDrawDist (0)); 77 double dist0 (getCircleDrawDist (0));
78 double dist1 (getCircleDrawDist (1)); 78 double dist1 (getCircleDrawDist (1));
79 LDDocumentPtr refFile; 79 LDDocumentPtr refFile;
80 Matrix transform; 80 Matrix transform;
81 bool circleOrDisc = false; 81 bool circleOrDisc = false;
84 qSwap (dist0, dist1); 84 qSwap (dist0, dist1);
85 85
86 if (dist0 == dist1) 86 if (dist0 == dist1)
87 { 87 {
88 // If the radii are the same, there's no ring space to fill. Use a circle. 88 // If the radii are the same, there's no ring space to fill. Use a circle.
89 refFile = GetDocument (MakeRadialFileName (::Circle, segs, segs, 0)); 89 refFile = GetPrimitive (::Circle, segments, divisions, 0);
90 transform = getCircleDrawMatrix (dist0); 90 transform = getCircleDrawMatrix (dist0);
91 circleOrDisc = true; 91 circleOrDisc = true;
92 } 92 }
93 elif (dist0 == 0 or dist1 == 0) 93 elif (dist0 == 0 or dist1 == 0)
94 { 94 {
95 // If either radii is 0, use a disc. 95 // If either radii is 0, use a disc.
96 refFile = GetDocument (MakeRadialFileName (::Disc, segs, segs, 0)); 96 refFile = GetPrimitive (::Disc, segments, divisions, 0);
97 transform = getCircleDrawMatrix ((dist0 != 0) ? dist0 : dist1); 97 transform = getCircleDrawMatrix ((dist0 != 0) ? dist0 : dist1);
98 circleOrDisc = true; 98 circleOrDisc = true;
99 } 99 }
100 elif (g_RingFinder.findRings (dist0, dist1)) 100 elif (g_RingFinder.findRings (dist0, dist1))
101 { 101 {
102 // The ring finder found a solution, use that. Add the component rings to the file. 102 // The ring finder found a solution, use that. Add the component rings to the file.
103 for (const RingFinder::Component& cmp : g_RingFinder.bestSolution()->getComponents()) 103 for (const RingFinder::Component& cmp : g_RingFinder.bestSolution()->getComponents())
104 { 104 {
105 // Get a ref file for this primitive. If we cannot find it in the 105 refFile = GetPrimitive (::Ring, segments, divisions, cmp.num);
106 // LDraw library, generate it.
107 if ((refFile = ::GetDocument (MakeRadialFileName (::Ring, segs, segs, cmp.num))) == null)
108 {
109 refFile = GeneratePrimitive (::Ring, segs, segs, cmp.num);
110 refFile->setImplicit (false);
111 }
112
113 LDSubfilePtr ref = LDSpawn<LDSubfile>(); 106 LDSubfilePtr ref = LDSpawn<LDSubfile>();
114 ref->setFileInfo (refFile); 107 ref->setFileInfo (refFile);
115 ref->setTransform (getCircleDrawMatrix (cmp.scale)); 108 ref->setTransform (getCircleDrawMatrix (cmp.scale));
116 ref->setPosition (m_drawedVerts[0]); 109 ref->setPosition (m_drawedVerts[0]);
117 ref->setColor (MainColor()); 110 ref->setColor (MainColor());
132 templ.setCoordinate (localx, x0); 125 templ.setCoordinate (localx, x0);
133 templ.setCoordinate (localy, y0); 126 templ.setCoordinate (localy, y0);
134 templ.setCoordinate (localz, renderer()->getDepthValue()); 127 templ.setCoordinate (localz, renderer()->getDepthValue());
135 128
136 // Calculate circle coords 129 // Calculate circle coords
137 MakeCircle (segs, divs, dist0, c0); 130 MakeCircle (segments, divisions, dist0, c0);
138 MakeCircle (segs, divs, dist1, c1); 131 MakeCircle (segments, divisions, dist1, c1);
139 132
140 for (int i = 0; i < segs; ++i) 133 for (int i = 0; i < segments; ++i)
141 { 134 {
142 Vertex v0, v1, v2, v3; 135 Vertex v0, v1, v2, v3;
143 v0 = v1 = v2 = v3 = templ; 136 v0 = v1 = v2 = v3 = templ;
144 v0.setCoordinate (localx, v0[localx] + c0[i].x1()); 137 v0.setCoordinate (localx, v0[localx] + c0[i].x1());
145 v0.setCoordinate (localy, v0[localy] + c0[i].y1()); 138 v0.setCoordinate (localy, v0[localy] + c0[i].y1());
183 { 176 {
184 renderer()->drawBlip (painter, renderer()->coordconv3_2 (renderer()->position3D())); 177 renderer()->drawBlip (painter, renderer()->coordconv3_2 (renderer()->position3D()));
185 return; 178 return;
186 } 179 }
187 180
188 QVector<Vertex> verts, verts2; 181 QVector<Vertex> innerverts, outerverts;
189 const double dist0 = getCircleDrawDist (0), 182 QVector<QPointF> innerverts2d, outerverts2d;
190 dist1 = (m_drawedVerts.size() >= 2) ? getCircleDrawDist (1) : -1; 183 const double innerdistance (getCircleDrawDist (0));
191 const int segs (g_win->ringToolHiRes() ? HighResolution : LowResolution); 184 const double outerdistance (m_drawedVerts.size() >= 2 ? getCircleDrawDist (1) : -1);
192 const double angleUnit = (2 * Pi) / segs; 185 const int divisions (g_win->ringToolHiRes() ? HighResolution : LowResolution);
186 const int segments (g_win->ringToolSegments());
187 const double angleUnit (2 * Pi / divisions);
193 Axis relX, relY; 188 Axis relX, relY;
194 QVector<QPoint> ringpoints, circlepoints, circle2points;
195
196 renderer()->getRelativeAxes (relX, relY); 189 renderer()->getRelativeAxes (relX, relY);
197 190
198 // Calculate the preview positions of vertices 191 // Calculate the preview positions of vertices
199 for (int i = 0; i < segs; ++i) 192 for (int i = 0; i < segments + 1; ++i)
200 { 193 {
201 Vertex v (Origin); 194 Vertex v (Origin);
202 v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * dist0)); 195 v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * innerdistance));
203 v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * dist0)); 196 v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * innerdistance));
204 verts << v; 197 innerverts << v;
205 198 innerverts2d << renderer()->coordconv3_2 (v);
206 if (dist1 != -1) 199
207 { 200 if (outerdistance != -1)
208 v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * dist1)); 201 {
209 v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * dist1)); 202 v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * outerdistance));
210 verts2 << v; 203 v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * outerdistance));
211 } 204 outerverts << v;
212 } 205 outerverts2d << renderer()->coordconv3_2 (v);
213 206 }
214 int i = 0; 207 }
215 for (const Vertex& v : verts + verts2) 208
216 { 209 QVector<QLineF> lines (segments);
217 // Calculate the 2D point of the vertex 210
218 QPoint point (renderer()->coordconv3_2 (v)); 211 if (outerdistance != -1 and outerdistance != innerdistance)
219 212 {
220 // Draw a green blip at where it is 213 painter.setBrush (m_polybrush);
214 painter.setPen (Qt::NoPen);
215
216 // Compile polygons
217 for (int i = 0; i < segments; ++i)
218 {
219 QVector<QPointF> points;
220 points << innerverts2d[i]
221 << innerverts2d[i + 1]
222 << outerverts2d[i + 1]
223 << outerverts2d[i];
224 painter.drawPolygon (QPolygonF (points));
225 lines << QLineF (innerverts2d[i], innerverts2d[i + 1]);
226 lines << QLineF (outerverts2d[i], outerverts2d[i + 1]);
227 }
228
229 // Add bordering edges for unclosed rings/discs
230 if (segments != divisions)
231 {
232 lines << QLineF (innerverts2d.first(), outerverts2d.first());
233 lines << QLineF (innerverts2d.last(), outerverts2d.last());
234 }
235 }
236 else
237 {
238 for (int i = 0; i < segments; ++i)
239 lines << QLineF (innerverts2d[i], innerverts2d[i + 1]);
240 }
241
242 // Draw a green blips at where the points are
243 for (QPointF const& point : innerverts2d + outerverts2d)
221 renderer()->drawBlip (painter, point); 244 renderer()->drawBlip (painter, point);
222 245
223 // Add it to the list of points for the green ring fill. 246 // Draw edge lines
224 ringpoints << point;
225
226 // Also add the circle points to separate lists
227 if (i < verts.size())
228 circlepoints << point;
229 else
230 circle2points << point;
231
232 ++i;
233 }
234
235 // Insert the first point as the seventeenth one so that
236 // the ring polygon is closed properly.
237 if (ringpoints.size() >= segs)
238 ringpoints.insert (segs, ringpoints[0]);
239
240 // Same for the outer ring. Note that the indices are offset by 1
241 // because of the insertion done above bumps the values.
242 if (ringpoints.size() >= segs * 2 + 1)
243 ringpoints.insert (segs * 2 + 1, ringpoints[segs + 1]);
244
245 // Draw the ring
246 painter.setBrush ((m_drawedVerts.size() >= 2) ? m_polybrush : Qt::NoBrush);
247 painter.setPen (Qt::NoPen);
248 painter.drawPolygon (QPolygon (ringpoints));
249
250 // Draw the circles
251 painter.setBrush (Qt::NoBrush);
252 painter.setPen (renderer()->linePen()); 247 painter.setPen (renderer()->linePen());
253 painter.drawPolygon (QPolygon (circlepoints)); 248 painter.drawLines (lines);
254 painter.drawPolygon (QPolygon (circle2points));
255 249
256 // Draw the current radius in the middle of the circle. 250 // Draw the current radius in the middle of the circle.
257 QPoint origin = renderer()->coordconv3_2 (m_drawedVerts[0]); 251 QPoint origin = renderer()->coordconv3_2 (m_drawedVerts[0]);
258 QString label = QString::number (dist0); 252 QString label = QString::number (innerdistance);
259 painter.setPen (renderer()->textPen()); 253 painter.setPen (renderer()->textPen());
260 painter.drawText (origin.x() - (metrics.width (label) / 2), origin.y(), label); 254 painter.drawText (origin.x() - (metrics.width (label) / 2), origin.y(), label);
261 255
262 if (m_drawedVerts.size() >= 2) 256 if (m_drawedVerts.size() >= 2)
263 { 257 {
264 painter.drawText (origin.x() - (metrics.width (label) / 2), 258 painter.drawText (origin.x() - (metrics.width (label) / 2),
265 origin.y() + metrics.height(), QString::number (dist1)); 259 origin.y() + metrics.height(), QString::number (outerdistance));
266 } 260 }
267 } 261 }
268 262
269 bool CircleMode::mouseReleased (MouseEventData const& data) 263 bool CircleMode::mouseReleased (MouseEventData const& data)
270 { 264 {

mercurial