@@ -161,7 +161,8 @@ std::string ShapeElement::to_string() const
161161 } case ShapeElementType::CircularArc: {
162162 return " CircularArc start " + start.to_string ()
163163 + " end " + end.to_string ()
164- + " center " + center.to_string ();
164+ + " center " + center.to_string ()
165+ + ((anticlockwise)? " anticlockwise" : " clockwise" );
165166 }
166167 }
167168 return " " ;
@@ -268,21 +269,28 @@ std::vector<ShapeElement> irregular::approximate_circular_arc_by_line_segments(
268269 " number_of_line_segments: " + std::to_string (number_of_line_segments) + " ." );
269270 }
270271
271- Angle angle = angle_radian (
272+ Angle angle = (circular_arc.anticlockwise )?
273+ angle_radian (
272274 circular_arc.start - circular_arc.center ,
273- circular_arc.end - circular_arc.center );
274- if (outer) {
275+ circular_arc.end - circular_arc.center ):
276+ angle_radian (
277+ circular_arc.end - circular_arc.center ,
278+ circular_arc.start - circular_arc.center );
279+ if ((outer && circular_arc.anticlockwise )
280+ || (!outer && !circular_arc.anticlockwise )) {
275281 if (angle < M_PI && number_of_line_segments < 2 ) {
276282 throw std::runtime_error (
277283 " packingsolver::irregular::circular_arc_to_line_segments: "
278- " at least 2 line segments are needed to outer approximate a circular arc with an angle <= PI; "
284+ " at least 2 line segments are needed to approximate the circular arc; "
285+ " circular_arc: " + circular_arc.to_string () + " ; "
279286 " outer: " + std::to_string (outer) + " ; "
280287 " angle: " + std::to_string (angle) + " ; "
281288 " number_of_line_segments: " + std::to_string (number_of_line_segments) + " ." );
282289 } else if (angle >= M_PI && number_of_line_segments < 3 ) {
283290 throw std::runtime_error (
284291 " packingsolver::irregular::circular_arc_to_line_segments: "
285- " at least 3 line segments are needed to outer approximate a circular arc with an angle >= PI; "
292+ " at least 3 line segments are needed to approximate the circular arc; "
293+ " circular_arc: " + circular_arc.to_string () + " ; "
286294 " outer: " + std::to_string (outer) + " ; "
287295 " angle: " + std::to_string (angle) + " ; "
288296 " number_of_line_segments: " + std::to_string (number_of_line_segments) + " ." );
@@ -297,11 +305,17 @@ std::vector<ShapeElement> irregular::approximate_circular_arc_by_line_segments(
297305 line_segment_id < number_of_line_segments - 1 ;
298306 ++line_segment_id) {
299307 Angle angle_cur = (angle * (line_segment_id + 1 )) / (number_of_line_segments - 1 );
308+ if (!circular_arc.anticlockwise )
309+ angle_cur *= -1 ;
300310 Point point_circle;
301- point_circle.x = circular_arc.center .x + radius * std::cos (angle_cur);
302- point_circle.y = circular_arc.center .y + radius * std::sin (angle_cur);
311+ point_circle.x = circular_arc.center .x
312+ + std::cos (angle_cur) * (circular_arc.start .x - circular_arc.center .x )
313+ - std::sin (angle_cur) * (circular_arc.start .y - circular_arc.center .y );
314+ point_circle.y = circular_arc.center .y
315+ + std::sin (angle_cur) * (circular_arc.start .x - circular_arc.center .x )
316+ + std::cos (angle_cur) * (circular_arc.start .y - circular_arc.center .y );
303317 Point point_cur;
304- if (! outer) {
318+ if ((outer && !circular_arc. anticlockwise ) || (! outer && circular_arc. anticlockwise ) ) {
305319 point_cur = point_circle;
306320 } else {
307321 // https://en.wikipedia.org/wiki/Tangent_lines_to_circles#Cartesian_equation
@@ -696,9 +710,13 @@ Shape packingsolver::irregular::build_shape(
696710 element.type = type;
697711 element.start = point_prev;
698712 element.end = {points[pos].x , points[pos].y };
713+ element.center = center;
714+ element.anticlockwise = anticlockwise;
699715 if (!path || pos > 0 )
700716 shape.elements .push_back (element);
701717 point_prev = element.end ;
718+ anticlockwise = true ;
719+ center = {0 , 0 };
702720 type = ShapeElementType::LineSegment;
703721 } else {
704722 anticlockwise = (point.type == 1 );
0 commit comments