@@ -368,3 +368,101 @@ std::vector<Shape> packingsolver::irregular::borders(
368368
369369 return res;
370370}
371+
372+ Shape irregular::inflate (
373+ const Shape& shape,
374+ LengthDbl value)
375+ {
376+ Shape inflated_shape;
377+ inflated_shape.elements .reserve (shape.elements .size ());
378+
379+ for (ElementPos element_pos = 0 ;
380+ element_pos < (ElementPos)shape.elements .size ();
381+ ++element_pos) {
382+ const ShapeElement& element = shape.elements [element_pos];
383+ ElementPos element_next_pos = (element_pos + 1 ) % shape.elements .size ();
384+ const ShapeElement& element_next = shape.elements [element_next_pos];
385+
386+ // calculate the normal vector of the current edge
387+ LengthDbl dx = element.end .x - element.start .x ;
388+ LengthDbl dy = element.end .y - element.start .y ;
389+ LengthDbl length = std::sqrt (dx * dx + dy * dy);
390+ LengthDbl nx = dy / length;
391+ LengthDbl ny = -dx / length;
392+
393+ // calculate the normal vector of the next edge
394+ LengthDbl dx_next = element_next.end .x - element_next.start .x ;
395+ LengthDbl dy_next = element_next.end .y - element_next.start .y ;
396+ LengthDbl length_next = std::sqrt (dx_next * dx_next + dy_next * dy_next);
397+ LengthDbl nx_next = dy_next / length_next;
398+ LengthDbl ny_next = -dx_next / length_next;
399+
400+ // calculate the average normal vector of the vertex
401+ LengthDbl nx_avg = (nx + nx_next) / 2 ;
402+ LengthDbl ny_avg = (ny + ny_next) / 2 ;
403+ LengthDbl length_avg = std::sqrt (nx_avg * nx_avg + ny_avg * ny_avg);
404+ nx_avg /= length_avg;
405+ ny_avg /= length_avg;
406+
407+ // create a new edge
408+ ShapeElement new_element;
409+ new_element.type = element.type ;
410+ new_element.start = Point{
411+ element.start .x + nx * value,
412+ element.start .y + ny * value
413+ };
414+ new_element.end = Point{
415+ element.end .x + nx * value,
416+ element.end .y + ny * value
417+ };
418+
419+ // add the arc at the vertex
420+ if (element_pos > 0 ) {
421+ ShapeElement arc_element;
422+ arc_element.type = ShapeElementType::CircularArc;
423+ arc_element.start = Point{
424+ element.start .x + nx_avg * value,
425+ element.start .y + ny_avg * value
426+ };
427+ arc_element.end = new_element.start ;
428+ inflated_shape.elements .push_back (arc_element);
429+ }
430+
431+ inflated_shape.elements .push_back (new_element);
432+ }
433+
434+ // add the arc at the last vertex
435+ if (!shape.elements .empty ()) {
436+ const ShapeElement& first_element = shape.elements .front ();
437+ const ShapeElement& last_element = shape.elements .back ();
438+
439+ LengthDbl dx_first = first_element.end .x - first_element.start .x ;
440+ LengthDbl dy_first = first_element.end .y - first_element.start .y ;
441+ LengthDbl length_first = std::sqrt (dx_first * dx_first + dy_first * dy_first);
442+ LengthDbl nx_first = dy_first / length_first;
443+ LengthDbl ny_first = -dx_first / length_first;
444+
445+ LengthDbl dx_last = last_element.end .x - last_element.start .x ;
446+ LengthDbl dy_last = last_element.end .y - last_element.start .y ;
447+ LengthDbl length_last = std::sqrt (dx_last * dx_last + dy_last * dy_last);
448+ LengthDbl nx_last = dy_last / length_last;
449+ LengthDbl ny_last = -dx_last / length_last;
450+
451+ LengthDbl nx_avg = (nx_first + nx_last) / 2 ;
452+ LengthDbl ny_avg = (ny_first + ny_last) / 2 ;
453+ LengthDbl length_avg = std::sqrt (nx_avg * nx_avg + ny_avg * ny_avg);
454+ nx_avg /= length_avg;
455+ ny_avg /= length_avg;
456+
457+ ShapeElement arc_element;
458+ arc_element.type = ShapeElementType::CircularArc;
459+ arc_element.start = Point{
460+ first_element.start .x + nx_avg * value,
461+ first_element.start .y + ny_avg * value
462+ };
463+ arc_element.end = inflated_shape.elements .front ().start ;
464+ inflated_shape.elements .push_back (arc_element);
465+ }
466+
467+ return inflated_shape;
468+ }
0 commit comments