57 typedef AlocatingAlignedBuffer<Polyline<t_dims, t_type, t_vertex>, 32> PolyLineBuffer;
61 , m_cache_length(Constant<t_type>::Invalid)
66 , m_cache_length(Constant<t_type>::Invalid)
68 Polyline(
const Polyline& polygon) noexcept
69 : m_vertices(polygon.m_vertices)
70 , m_cache_bounds(polygon.m_cache_bounds)
71 , m_cache_length(polygon.m_cache_length)
73 Polyline(Polyline&& polygon) noexcept
78 std::swap(m_vertices, polygon.m_vertices);
79 std::swap(m_cache_bounds, polygon.m_cache_bounds);
80 std::swap(m_cache_length, polygon.m_cache_length);
98 for (
uint04 i = 0; i < m_vertices.size(); i++)
100 m_cache_bounds.addToBounds(m_vertices[i]);
103 return m_cache_bounds;
106 decltype(
auto) begin()
108 return m_vertices.begin();
110 decltype(
auto) begin()
const
112 return m_vertices.begin();
115 decltype(
auto) begin(
uint04 index)
const
117 return m_vertices.begin(index);
119 decltype(
auto) begin(
uint04 index)
121 return m_vertices.begin(index);
126 return m_vertices.end();
128 decltype(
auto) end()
const
130 return m_vertices.end();
148 return m_vertices[index];
196 return m_vertices.size();
211 if (m_vertices.size() == 0)
214 return m_vertices.size() - 1;
249 void addAndSimplify(
const t_vertex&
vertex)
268 m_vertices.add(index,
vertex);
271 void addAndSimplify(
uint04 index,
const t_vertex&
vertex)
279 m_vertices.add(index,
vertex);
284 m_vertices.add(index,
vertex);
287 if (
segment(index).
template isParallel<t_type>(
segment(index - 1), 0.00001))
294 if (
segment(index - 1).
template isParallel<t_type>(
segment(index - 2), 0.00001))
317 if (m_vertices[index] !=
vertex)
319 m_vertices[index] =
vertex;
337 m_vertices.removeIndex(index);
352 return m_vertices.last();
364 m_vertices.removeLast();
384 else if (i > 0 &&
segment(i).
template isParallel<t_type>(
segment(i - 1), 0.00001))
414 template<u
int01 t_new_dims,
class t_new_type,
class t_new_vertex_type = Vertex<t_new_dims, t_new_type>>
415 Polyline<t_dims, t_new_type, t_new_vertex_type>
as()
const
417 Polyline<t_dims, t_new_type, t_new_vertex_type> poly;
434 template<
class t_precision>
453 return m_cache_length;
469 template<
class t_
inter_type>
470 constexpr inline t_vertex
pointAt(t_inter_type value)
const
476 constexpr inline t_vertex pointAtLength(
fltp08 value)
const
479 return Constant<t_vertex>::Invalid;
480 fltp08 accumulated_distance = 0;
484 if (accumulated_distance + local_distance > value)
486 fltp08 line_percent =
clip((value - accumulated_distance) / local_distance, 0.0, 1.0);
491 accumulated_distance += local_distance;
511 return (m_vertices == polygon.m_vertices);
515 m_vertices = polygon.m_vertices;
516 m_cache_length = polygon.m_cache_length;
517 m_cache_bounds = polygon.m_cache_bounds;
520 Polyline& operator=(Polyline&& polygon)
noexcept
522 std::swap(m_vertices, polygon.m_vertices);
523 m_cache_length = polygon.m_cache_length;
524 m_cache_bounds = polygon.m_cache_bounds;
527 Polyline<t_dims, t_type> breakIntoSegmentsByLength(t_type
length)
const
529 Polyline<t_dims, t_type> new_poly;
533 t_type remainder_distance(0);
538 if (seg_length + remainder_distance >
length)
540 t_type local_accumulation =
length - remainder_distance;
541 lib_assert(local_accumulation > 0.0,
"Bad accumulation");
542 auto ray =
segment(i).ray().template normalized<fltp08>();
545 new_poly.add(
segment(i).
vertex(A) + ray * local_accumulation);
546 local_accumulation +=
length;
547 }
while (local_accumulation < seg_length);
548 remainder_distance =
length + seg_length - local_accumulation;
552 remainder_distance += seg_length;
557 Polyline<t_dims, t_type> breakIntoSegmentsByDistance(t_type d)
const
559 t_type dist_squared = d * d;
560 Polyline<t_dims, t_type> new_poly;
566 if (distanceSquared(new_poly.lastVertex(),
vertex(i)) > dist_squared)
569 LineSegment<t_dims, t_type> seg(
vertex(i - 1),
vertex(i));
570 const Vector<t_dims, t_type> ab = seg.ray();
571 const Vector<t_dims, t_type> ap = new_poly.lastVertex() - seg[A];
572 Vector<t_dims, t_type> normal = ab.template normalized<t_type>();
573 if(ap != 0.0 && !
equals(ab, ap, 0.000001) && !
equals(ab, -ap, 0.000001))
577 t_type sum = (ab * ap).sum();
578 const t_type mag_squared = ab.magnitudeSquared();
580 const Vector<t_dims, t_type> p0 = seg[A] + (ab * sum);
581 t_type new_distance =
sqrt(dist_squared - distanceSquared(p0, new_poly.lastVertex()));
582 new_poly.add(new_distance * normal + p0);
585 while (distanceSquared(new_poly.lastVertex(),
vertex(i)) > dist_squared)
587 new_poly.add(d * normal + new_poly.lastVertex());
594 PolyLineBuffer breakIntoPolylinesByLength(t_type max_distance)
const
596 PolyLineBuffer new_polys;
599 Polyline<t_dims, t_type> new_poly;
601 t_type accumulated_distance = 0;
604 t_type local_distance = distance<t_type>(
vertex(i - 1),
vertex(i));
605 while (accumulated_distance + local_distance > max_distance)
607 auto direction = (
vertex(i) - new_poly.lastVertex()).
template normalized<t_type>();
608 t_type adjusted_distance = max_distance - accumulated_distance;
610 auto final_vertex = adjusted_distance * direction + new_poly.lastVertex();
611 new_poly.add(final_vertex);
612 new_polys.add(new_poly);
615 new_poly.add(final_vertex);
616 local_distance = local_distance - adjusted_distance;
617 accumulated_distance = 0.0;
621 accumulated_distance += local_distance;
623 new_polys.add(new_poly);
627 Polyline<t_dims, t_type> clipPolyline(
const Bounds<t_vertex::NumberOfDimensions(), t_type>&
bounds)
const
629 if (
bounds.contains<
true>(this->bounds()))
631 if (!
bounds.intersects(this->bounds()))
636 LineSegment<t_vertex::NumberOfDimensions(), t_type> line(
vertex(ii),
vertex(ii + 1));
640 if (polyline.vertexCount() == 0 || polyline.lastVertex() != line.vertex(A))
641 polyline.add(line.vertex(A));
642 polyline.add(line.vertex(B));
658 inline void invalidateCache()
const
660 m_cache_length = Constant<t_type>::Invalid;
661 m_cache_bounds = Constant<Bounds<t_dims, t_type>>
::Invalid;
675 void updateVertices(
const Buffer<t_vertex>&
vertices)
682 Buffer<t_vertex> m_vertices;
692 mutable Bounds<t_dims, t_type, t_vertex> m_cache_bounds;
702 mutable t_type m_cache_length;