11#ifndef JAU_GAMP_GRAPH_OUTLINE_HPP_
12#define JAU_GAMP_GRAPH_OUTLINE_HPP_
30 using namespace jau::enums;
31 using namespace jau::math;
33 using jau::math::geom::AABBox3f;
34 using jau::math::geom::plane::AffineTransform;
55 enum class DirtyBits : uint16_t {
67 mutable DirtyBits m_dirtyBits;
68 mutable bool m_complexShape;
78 : m_vertices(vertCapacity),
79 m_closed(false), m_bbox(),
81 m_dirtyBits(DirtyBits::none),
85 constexpr void reserve(
size_type newVertCapacity) { m_vertices.reserve(newVertCapacity); }
87 constexpr bool empty() const noexcept {
return m_vertices.empty(); }
105 if( position < m_vertices.size() ) {
106 m_dirtyBits |= DirtyBits::bounds | DirtyBits::winding | DirtyBits::complexShape;
107 m_vertices.erase(position);
112 return m_vertices.size() == 0;
119 return m_vertices[m_vertices.size()-1];
122 constexpr bool isClosed() const noexcept {
return m_closed; }
142 m_vertices.push_back(first);
144 m_vertices.insert(m_vertices.begin(), last);
160 if( !
is_set(m_dirtyBits, DirtyBits::winding) ) {
165 m_winding = Winding::CCW;
169 m_dirtyBits &= ~DirtyBits::winding;
182 if( enforce != had_winding ) {
190 m_dirtyBits &= ~DirtyBits::winding;
204 if( !
is_set(m_dirtyBits, DirtyBits::complexShape) ) {
205 return m_complexShape;
207 m_complexShape = !
isConvex1(m_vertices,
true);
209 m_dirtyBits &= ~DirtyBits::complexShape;
210 return m_complexShape;
214 void validateBoundingBox() const noexcept {
217 for(
const Vertex& v : m_vertices) {
224 if (
is_set(m_dirtyBits, DirtyBits::bounds) ) {
225 validateBoundingBox();
239 m_vertices.push_back(
vertex);
240 if ( !
is_set(m_dirtyBits, DirtyBits::bounds) ) {
241 m_bbox.resize(
vertex.coord());
243 m_dirtyBits |= DirtyBits::winding | DirtyBits::complexShape;
257 m_vertices.insert(position,
vertex);
258 if ( !
is_set(m_dirtyBits, DirtyBits::bounds) ) {
259 m_bbox.resize(
vertex.coord());
261 m_dirtyBits |= DirtyBits::winding | DirtyBits::complexShape;
267 for(
const Vertex& v : m_vertices) {
270 newOutline.m_closed = m_closed;
281 const float otherSize = other.bounds().size();
284 }
else if(thisSize < otherSize){
301 if(
bounds() != o.bounds() ) {
305 if(
vertex(i) != o.vertex(i) ) {
bool setClosed(bool closeTail)
Ensure this outline is closed.
constexpr void reserve(size_type newVertCapacity)
void addVertex(const Vertex &vertex)
Appends a vertex to the outline loop/strip.
constexpr const VertexList & vertices() const noexcept
bool isEmpty() const noexcept
bool isComplex() const noexcept
Returns cached or computed result if whether this Outlines polyline is a complex shape.
constexpr bool empty() const noexcept
constexpr bool isClosed() const noexcept
constexpr bool operator==(const Outline &o) const noexcept
constexpr const Vertex & vertex(size_type i) const noexcept
constexpr size_type vertexCount() const noexcept
void setWinding(Winding enforce)
Sets Winding to this outline.
constexpr Vertex & vertex(size_type i) noexcept
constexpr Outline(size_type vertCapacity)
Outline transform(const AffineTransform &t) const
Returns a transformed copy of this instance using the given AffineTransform.
constexpr VertexList & vertices() noexcept
int compareTo(const Outline &other) const noexcept
Compare two outline's Bounding Box size.
Winding getWinding() const noexcept
Returns the cached or computed winding of this Outlines polyline using VectorUtil#area(ArrayList).
const AABBox3f & bounds() const noexcept
void removeVertex(size_type position)
Removes the Vertex element at the given position.
const Vertex & lastVertex() const noexcept
void addVertex(size_type position, const Vertex &vertex)
Insert the Vertex element at the given position to the outline loop/strip.
static constexpr size_type max_elements
byte-size int32_t limit: 536'870'911 (FIXME: Adjust to actual type, i.e. Vertex = 2x Vec3f?...
constexpr const Vec3f & coord() const noexcept
Implementation of a dynamic linear array storage, aka vector, including relative positional access.
constexpr void push_back(const value_type &x)
Like std::vector::push_back(), copy.
Axis Aligned Bounding Box.
constexpr AABBox3f & reset() noexcept
Reset this box to the inverse low/high, allowing the next resize(float, float, float) command to hit.
constexpr float size() const noexcept
Get the size of this aabbox3f where the size is represented by the length of the vector between low a...
AABBox3f & resize(const AABBox3f &o) noexcept
Resize the aabbox3f to encapsulate another AABox.
#define JAU_MAKE_BITFIELD_ENUM_STRING_MEMBER(type,...)
constexpr bool is_set(const E mask, const E bits) noexcept
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr equals2(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
jau::darray< Outline, jau::nsize_t > OutlineList
jau::darray< Vertex, uint32_t > VertexList
static bool isConvex1(const VertexList &polyline, bool shortIsConvex) noexcept
Returns whether the given on-curve polyline points denotes a convex shape with O(n) complexity.
constexpr Winding getWinding(const VertexList &vertices) noexcept
Compute the winding using the area2D() function over all vertices for complex shapes.