implement finer approximati...
Stefan Schuermans authored 11 years ago
|
46) /* special handling for some entities
47) to avoid libdime's inexact conversion to lines */
48) dimeArc *arc;
49) dimeCircle *circle;
50) dimeEllipse *ellipse;
51) if ((arc = dynamic_cast<dimeArc *>(entity)))
52) traverse_arc(arc, matrix, p_ctx->precision, layer);
53) else if ((circle = dynamic_cast<dimeCircle *>(entity)))
54) traverse_circle(circle, matrix, p_ctx->precision, layer);
55) else if ((ellipse = dynamic_cast<dimeEllipse *>(entity)))
56) traverse_ellipse(ellipse, matrix, p_ctx->precision, layer);
57) else
58) traverse_generic(entity, matrix, layer); // default: libdime conversion
59)
60) return true; // continue enumeration
61) }
62)
63) /**
64) * @brief process a generic geometric object during DXF traversal
65) * @param[in] entity pointer to entity
66) * @param[in] matrix current DXF transformation matrix
67) * @param[in] layer layer to add the entitiy to
68) */
69) void traverse_generic(dimeEntity *entity, const dimeMatrix &matrix,
70) Layer &layer)
71) {
|
initial version, DXFs can b...
Stefan Schuermans authored 11 years ago
|
72) // get geometry data
73) dimeArray<dimeVec3f> vertices;
74) dimeArray<int> indices;
75) dimeVec3f extrusionDir;
76) dxfdouble thickness;
77) entity->extractGeometry(vertices, indices, extrusionDir, thickness);
78)
79) // transform geometry data
80) for (int v = 0; v < vertices.count(); ++v)
81) matrix.multMatrixVec(vertices[v]);
82)
83) // no indices -> entire vertices array forms a path
84) if (indices.count() == 0) {
85) Path &path = layer.addPath();
86) for (int v = 0; v < vertices.count(); ++v)
87) path.addPoint(vertices[v].x, vertices[v].y);
88) }
89)
90) // indices available: paths given by indices
91) else {
92) Path *path = &layer.addPath();
93) for (int i = 0; i < indices.count(); ++i) {
94) int v = indices[i];
95) // valid index: add to path
96) if (v >= 0 || v < vertices.count())
97) path->addPoint(vertices[v].x, vertices[v].y);
98) // invalid index: start new path
99) else
100) path = &layer.addPath();
101) }
102) }
|
implement finer approximati...
Stefan Schuermans authored 11 years ago
|
105) /**
106) * @brief process an arc during DXF traversal
107) * @param[in] circle pointer to arc entity
108) * @param[in] matrix current DXF transformation matrix
109) * @param[in] precision precision for conversion to lines
110) * @param[in] layer layer to add the entitiy to
111) */
112) void traverse_arc(dimeArc *arc, const dimeMatrix &matrix,
113) double precision, Layer &layer)
114) {
115) // get parameters (not yet transformed)
116) dimeVec3f center;
117) arc->getCenter(center);
118) double radius = arc->getRadius();
119) double start = arc->getStartAngle() * M_PI / 180.0;
120) double end = arc->getEndAngle() * M_PI / 180.0;
121)
122) // add arc to layer
123) traverse_add_circle(center, radius, start, end, precision, matrix, layer);
124) }
125)
126) /**
127) * @brief process a circle during DXF traversal
128) * @param[in] circle pointer to circle entity
129) * @param[in] matrix current DXF transformation matrix
130) * @param[in] precision precision for conversion to lines
131) * @param[in] layer layer to add the entitiy to
132) */
133) void traverse_circle(dimeCircle *circle, const dimeMatrix &matrix,
134) double precision, Layer &layer)
135) {
136) // get parameters and transform vertices
137) dimeVec3f center = circle->getCenter();
138) double radius = circle->getRadius();
139)
140) // add circle to layer
141) traverse_add_circle(center, radius, 0.0, 2.0 * M_PI,
142) precision, matrix, layer);
143) }
144)
145) /**
146) * @brief process an ellipse during DXF traversal
147) * @param[in] circle pointer to ellipse entity
148) * @param[in] matrix current DXF transformation matrix
149) * @param[in] precision precision for conversion to lines
150) * @param[in] layer layer to add the entitiy to
151) */
152) void traverse_ellipse(dimeEllipse *ellipse, const dimeMatrix &matrix,
153) double precision, Layer &layer)
154) {
155) // get parameters (not yet transformed)
156) dimeVec3f center = ellipse->getCenter();
157) dimeVec3f majorEnd = ellipse->getMajorAxisEndpoint();
158) double ratio = ellipse->getMinorMajorRatio();
159) double start = ellipse->getStartParam();
160) double end = ellipse->getEndParam();
161)
162) // add circle to layer
163) traverse_add_ellipse(center, majorEnd, ratio, start, end,
164) precision, matrix, layer);
165) }
166)
167) /**
168) * @brief add a circle to the layer
169) * @param[in] center center point
170) * @param[in] radius radius
171) * @param[in] start start angle in radians
172) * @param[in] end end angle in radians
173) * @param[in] precision precision for conversion to lines
174) * @param[in] matrix current DXF transformation matrix
175) * @param[in] layer layer to add the entitiy to
176) */
177) void traverse_add_circle(const dimeVec3f ¢er,
178) double radius, double start, double end,
179) double precision, const dimeMatrix &matrix,
180) Layer &layer)
181) {
182) // calculate number of segments to approximate part of circle with
183) unsigned int num_seg = traverse_calc_num_seg(radius, start, end, precision);
184)
185) // loop over all angles to calculate point for
186) if (end <= start)
187) end += 2.0 * M_PI;
188) unsigned int seg;
189) Path &path = layer.addPath();
190) for (seg = 0; seg <= num_seg; ++seg) {
191) double angle = (start * (num_seg - seg) + end * seg) / num_seg;
192)
193) // get point
194) double x = center.x + radius * cos(angle);
195) double y = center.y + radius * sin(angle);
196)
197) // transform point via current matrix and add it to path
198) dimeVec3f vertex(x, y, 0.0);
199) matrix.multMatrixVec(vertex);
200) path.addPoint(vertex.x, vertex.y);
201)
202) } // for seg
203) }
204)
205) /**
206) * @brief add ellipse to the layer
207) * @param[in] center center point
208) * @param[in] majorEnd endpoint of major axis
209) * @param[in] ratio ratio of minor to major axis
210) * @param[in] start start angle in radians
211) * @param[in] end end angle in radians
212) * @param[in] precision precision for conversion to lines
213) * @param[in] matrix current DXF transformation matrix
214) * @param[in] layer layer to add the entitiy to
215) */
216) void traverse_add_ellipse(const dimeVec3f ¢er, const dimeVec3f &majorEnd,
217) double ratio, double start, double end,
218) double precision, const dimeMatrix &matrix,
219) Layer &layer)
220) {
221) // calculate number of segments to approximate part of ellipse with
222) double majorRadius = (majorEnd - center).length();
223) double maxRadius = ratio <= 1.0 ? majorRadius : majorRadius * ratio;
224) unsigned int num_seg = traverse_calc_num_seg(maxRadius, start, end,
225) precision);
226)
227) // build transformation matrix: union circle -> ellipse
228) double maj_x = majorEnd.x;
229) double maj_y = majorEnd.y;
230) double min_x = -ratio * maj_y;
231) double min_y = ratio * maj_x;
232)
233) // loop over all angles to calculate point for
234) if (end <= start)
235) end += 2.0 * M_PI;
236) unsigned int seg;
237) Path &path = layer.addPath();
238) for (seg = 0; seg <= num_seg; ++seg) {
239) double angle = (start * (num_seg - seg) + end * seg) / num_seg;
240)
241) // get point on union circle
242) double uc_x = cos(angle);
243) double uc_y = sin(angle);
244) // transformation: union circle -> ellipse
245) double x = maj_x * uc_x + min_x * uc_y;
246) double y = maj_y * uc_x + min_y * uc_y;
247) // translate: move to center
248) x += center.x;
249) y += center.y;
250)
251) // transform point via current matrix and add it to path
252) dimeVec3f vertex(x, y, 0.0);
253) matrix.multMatrixVec(vertex);
254) path.addPoint(vertex.x, vertex.y);
255)
256) } // for seg
257) }
258)
259) /**
260) * @brief calculate number of segments to approx. part of circle/ellipse with
261) * @param[in] maxRadius radius of circle / maximum radius of ellipse
262) * @param[in] start start angle in radians
263) * @param[in] end end angle in radians
264) * @param[in] precision precision for conversion to lines
265) * @return number of segments to approximate circle/ellipse with
266) */
267) unsigned int traverse_calc_num_seg(double maxRadius, double start, double end,
268) double precision)
269) {
270) // calculate number of segments for full circle/ellipse
271) unsigned int num_seg;
272) double dist;
273) // double number of segments until precision is met (or maximum reached)
274) for (num_seg = TRAVERSE_CIRCLE_NUM_SEG_MIN;
275) num_seg < TRAVERSE_CIRCLE_NUM_SEG_MAX; num_seg *= 2) {
276) // maximum distance of circle and regular polygon with num_seg sides
277) dist = maxRadius * (1.0 - cos(M_PI / num_seg));
278) // precision met -> done
279) if (dist < precision)
280) break;
281) }
282)
283) // calculate number of segments for part of cirlce/ellipse
284) double angle = start < end ? end - start : 2.0 * M_PI + end - start;
285) num_seg = (unsigned int)ceil((double)num_seg * angle / (2.0 * M_PI));
286)
287) return num_seg;
|