Files
opennurbs/opennurbs_subd_iter.cpp
2024-08-22 01:43:04 -07:00

2144 lines
54 KiB
C++

//
// Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
#include "opennurbs.h"
#if !defined(ON_COMPILING_OPENNURBS)
// This check is included in all opennurbs source .c and .cpp files to insure
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
// and the opennurbs .h files alter what is declared and how it is declared.
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
#endif
#include "opennurbs_subd_data.h"
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDVertexArray
//
ON_SubDVertexArray::ON_SubDVertexArray(
const class ON_SubD& subd
)
{
m_subd.ShareDimple(subd);
unsigned int vertex_count = subd.VertexCount();
if (vertex_count > 0)
{
m_sp = subd.ActiveLevel().VertexArray();
m_a = m_sp.get();
if (nullptr != m_a)
m_vertex_count = vertex_count;
}
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDVertexArray::ON_SubDVertexArray(ON_SubDVertexArray&& src) ON_NOEXCEPT
: m_a(src.m_a)
, m_vertex_count(src.m_vertex_count)
, m_sp(std::move(src.m_sp))
{
m_subd.SwapDimple(src.m_subd);
src.m_subd.Destroy();
}
// The rvalue assignment operator calls ON_Object::operator=(ON_Object&&)
// which could throw exceptions. See the implementation of
// ON_Object::operator=(ON_Object&&) for details.
ON_SubDVertexArray& ON_SubDVertexArray::operator=(ON_SubDVertexArray&& src)
{
if (this != &src)
{
m_a = src.m_a;
m_subd.SwapDimple(src.m_subd);
m_vertex_count = src.m_vertex_count;
m_sp = std::move(src.m_sp);
src.m_subd.Destroy();
}
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDEdgeArray
//
ON_SubDEdgeArray::ON_SubDEdgeArray(
const class ON_SubD& subd
)
{
m_subd.ShareDimple(subd);
unsigned int edge_count = subd.EdgeCount();
if (edge_count > 0)
{
m_sp = subd.ActiveLevel().EdgeArray();
m_a = m_sp.get();
if (nullptr != m_a)
m_edge_count = edge_count;
}
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDEdgeArray::ON_SubDEdgeArray(ON_SubDEdgeArray&& src) ON_NOEXCEPT
: m_a(src.m_a)
, m_edge_count(src.m_edge_count)
, m_sp(std::move(src.m_sp))
{
m_subd.SwapDimple(src.m_subd);
src.m_subd.Destroy();
}
// The rvalue assignment operator calls ON_Object::operator=(ON_Object&&)
// which could throw exceptions. See the implementation of
// ON_Object::operator=(ON_Object&&) for details.
ON_SubDEdgeArray& ON_SubDEdgeArray::operator=(ON_SubDEdgeArray&& src)
{
if (this != &src)
{
m_a = src.m_a;
m_subd.SwapDimple(src.m_subd);
m_edge_count = src.m_edge_count;
m_sp = std::move(src.m_sp);
src.m_subd.Destroy();
}
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDFaceArray
//
ON_SubDFaceArray::ON_SubDFaceArray(
const class ON_SubD& subd
)
{
m_subd.ShareDimple(subd);
unsigned int face_count = subd.FaceCount();
if (face_count > 0)
{
m_sp = subd.ActiveLevel().FaceArray();
m_a = m_sp.get();
if (nullptr != m_a)
m_face_count = face_count;
}
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDFaceArray::ON_SubDFaceArray(ON_SubDFaceArray&& src) ON_NOEXCEPT
: m_a(src.m_a)
, m_face_count(src.m_face_count)
, m_sp(std::move(src.m_sp))
{
m_subd.SwapDimple(src.m_subd);
src.m_subd.Destroy();
}
// The rvalue assignment operator calls ON_Object::operator=(ON_Object&&)
// which could throw exceptions. See the implementation of
// ON_Object::operator=(ON_Object&&) for details.
ON_SubDFaceArray& ON_SubDFaceArray::operator=(ON_SubDFaceArray&& src)
{
if (this != &src)
{
m_a = src.m_a;
m_subd.SwapDimple(src.m_subd);
m_face_count = src.m_face_count;
m_sp = std::move(src.m_sp);
src.m_subd.Destroy();
}
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDComponentIdIterator
//
void ON_SubDHeap::InitializeComponentIdIterator(
ON_SubDComponentPtr::Type ctype,
class ON_SubDComponentIdIterator& cidit
) const
{
switch (ctype)
{
case ON_SubDComponentPtr::Type::Vertex:
cidit.m_component_type = ctype;
cidit.ON_FixedSizePoolIterator::Create(&m_fspv);
break;
case ON_SubDComponentPtr::Type::Edge:
cidit.m_component_type = ctype;
cidit.ON_FixedSizePoolIterator::Create(&m_fspe);
break;
case ON_SubDComponentPtr::Type::Face:
cidit.m_component_type = ctype;
cidit.ON_FixedSizePoolIterator::Create(&m_fspf);
break;
default:
ON_SUBD_ERROR("Invalid ctype");
break;
}
}
void ON_SubDimple::InitializeComponentIdIterator(
ON_SubDComponentPtr::Type ctype,
ON_SubDComponentIdIterator & cidit
) const
{
m_heap.InitializeComponentIdIterator(ctype, cidit);
}
const ON_SubDComponentBase* ON_SubDComponentIdIterator::FirstComponent()
{
for (const ON_SubDComponentBase* c = (const ON_SubDComponentBase*)FirstElement(); nullptr != c; c = (const ON_SubDComponentBase*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&c->m_id)[1])
return c;
}
return nullptr;
}
const ON_SubDComponentBase* ON_SubDComponentIdIterator::NextComponent()
{
for (const ON_SubDComponentBase* c = (const ON_SubDComponentBase*)NextElement(); nullptr != c; c = (const ON_SubDComponentBase*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&c->m_id)[1])
return c;
}
return nullptr;
}
const ON_SubDComponentBase* ON_SubDComponentIdIterator::CurrentComponent() const
{
return (const ON_SubDComponentBase*)CurrentElement();
};
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDVertexIterator
//
void ON_SubDHeap::InitializeVertexIdIterator(
class ON_SubDVertexIdIterator& vidit
) const
{
vidit.ON_FixedSizePoolIterator::Create(&m_fspv);
}
void ON_SubDimple::InitializeVertexIdIterator(
class ON_SubDVertexIdIterator& vidit
) const
{
m_heap.InitializeVertexIdIterator(vidit);
}
void ON_SubDVertexIdIterator::Internal_Init()
{
const ON_SubDimple* subdimple = m_subd_ref.SubD().SubDimple();
if (nullptr != subdimple)
subdimple->InitializeVertexIdIterator(*this);
}
ON_SubDVertexIdIterator::ON_SubDVertexIdIterator(const ON_SubDRef& subd_ref)
: m_subd_ref(subd_ref)
{
Internal_Init();
}
ON_SubDVertexIdIterator::ON_SubDVertexIdIterator(const ON_SubD& subd)
: m_subd_ref(ON_SubDRef::CreateReferenceForExperts(subd))
{
Internal_Init();
}
const ON_SubDVertex* ON_SubDVertexIdIterator::FirstVertex()
{
for (const ON_SubDVertex* v = (const ON_SubDVertex*)FirstElement(); nullptr != v; v = (const ON_SubDVertex*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&v->m_id)[1])
return v;
}
return nullptr;
}
const ON_SubDVertex* ON_SubDVertexIdIterator::NextVertex()
{
for (const ON_SubDVertex* v = (const ON_SubDVertex*)NextElement(); nullptr != v; v = (const ON_SubDVertex*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&v->m_id)[1])
return v;
}
return nullptr;
}
const ON_SubDVertex* ON_SubDVertexIdIterator::FirstVertexOnLevel(unsigned int level_index)
{
for (const ON_SubDVertex* v = (const ON_SubDVertex*)FirstElement(); nullptr != v; v = (const ON_SubDVertex*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&v->m_id)[1] && level_index == v->SubdivisionLevel())
return v;
}
return nullptr;
}
const ON_SubDVertex* ON_SubDVertexIdIterator::NextVertexOnLevel(unsigned int level_index)
{
for (const ON_SubDVertex* v = (const ON_SubDVertex*)NextElement(); nullptr != v; v = (const ON_SubDVertex*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&v->m_id)[1] && level_index == v->SubdivisionLevel())
return v;
}
return nullptr;
}
const ON_SubDVertex* ON_SubDVertexIdIterator::CurrentVertex() const
{
return (const ON_SubDVertex*)CurrentElement();
};
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDEdgeIterator
//
void ON_SubDHeap::InitializeEdgeIdIterator(
class ON_SubDEdgeIdIterator& eidit
) const
{
eidit.ON_FixedSizePoolIterator::Create(&m_fspe);
}
void ON_SubDimple::InitializeEdgeIdIterator(
class ON_SubDEdgeIdIterator& eidit
) const
{
m_heap.InitializeEdgeIdIterator(eidit);
}
void ON_SubDEdgeIdIterator::Internal_Init()
{
const ON_SubDimple* subdimple = m_subd_ref.SubD().SubDimple();
if (nullptr != subdimple)
subdimple->InitializeEdgeIdIterator(*this);
}
ON_SubDEdgeIdIterator::ON_SubDEdgeIdIterator(const ON_SubDRef& subd_ref)
: m_subd_ref(subd_ref)
{
Internal_Init();
}
ON_SubDEdgeIdIterator::ON_SubDEdgeIdIterator(const ON_SubD& subd)
: m_subd_ref(ON_SubDRef::CreateReferenceForExperts(subd))
{
Internal_Init();
}
const ON_SubDEdge* ON_SubDEdgeIdIterator::FirstEdge()
{
for (const ON_SubDEdge* e = (const ON_SubDEdge*)FirstElement(); nullptr != e; e = (const ON_SubDEdge*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&e->m_id)[1])
return e;
}
return nullptr;
}
const ON_SubDEdge* ON_SubDEdgeIdIterator::NextEdge()
{
for (const ON_SubDEdge* e = (const ON_SubDEdge*)NextElement(); nullptr != e; e = (const ON_SubDEdge*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&e->m_id)[1])
return e;
}
return nullptr;
}
const ON_SubDEdge* ON_SubDEdgeIdIterator::FirstEdgeOnLevel(unsigned int level_index)
{
for (const ON_SubDEdge* e = (const ON_SubDEdge*)FirstElement(); nullptr != e; e = (const ON_SubDEdge*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&e->m_id)[1] && level_index == e->SubdivisionLevel())
return e;
}
return nullptr;
}
const ON_SubDEdge* ON_SubDEdgeIdIterator::NextEdgeOnLevel(unsigned int level_index)
{
for (const ON_SubDEdge* e = (const ON_SubDEdge*)NextElement(); nullptr != e; e = (const ON_SubDEdge*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&e->m_id)[1] && level_index == e->SubdivisionLevel())
return e;
}
return nullptr;
}
const ON_SubDEdge* ON_SubDEdgeIdIterator::CurrentEdge() const
{
return (const ON_SubDEdge*)CurrentElement();
};
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDFaceIterator
//
void ON_SubDHeap::InitializeFaceIdIterator(
class ON_SubDFaceIdIterator& fidit
) const
{
fidit.ON_FixedSizePoolIterator::Create(&m_fspf);
}
void ON_SubDimple::InitializeFaceIdIterator(
class ON_SubDFaceIdIterator& fidit
) const
{
m_heap.InitializeFaceIdIterator(fidit);
}
void ON_SubDFaceIdIterator::Internal_Init()
{
const ON_SubDimple* subdimple = m_subd_ref.SubD().SubDimple();
if (nullptr != subdimple)
subdimple->InitializeFaceIdIterator(*this);
}
ON_SubDFaceIdIterator::ON_SubDFaceIdIterator(const ON_SubDRef& subd_ref)
: m_subd_ref(subd_ref)
{
Internal_Init();
}
ON_SubDFaceIdIterator::ON_SubDFaceIdIterator(const ON_SubD& subd)
: m_subd_ref(ON_SubDRef::CreateReferenceForExperts(subd))
{
Internal_Init();
}
const ON_SubDFace* ON_SubDFaceIdIterator::FirstFace()
{
for (const ON_SubDFace* f = (const ON_SubDFace*)FirstElement(); nullptr != f; f = (const ON_SubDFace*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&f->m_id)[1])
return f;
}
return nullptr;
}
const ON_SubDFace* ON_SubDFaceIdIterator::NextFace()
{
for (const ON_SubDFace* f = (const ON_SubDFace*)NextElement(); nullptr != f; f = (const ON_SubDFace*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&f->m_id)[1])
return f;
}
return nullptr;
}
const ON_SubDFace* ON_SubDFaceIdIterator::FirstFaceOnLevel(unsigned int level_index)
{
for (const ON_SubDFace* f = (const ON_SubDFace*)FirstElement(); nullptr != f; f = (const ON_SubDFace*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&f->m_id)[1] && level_index == f->SubdivisionLevel())
return f;
}
return nullptr;
}
const ON_SubDFace* ON_SubDFaceIdIterator::NextFaceOnLevel(unsigned int level_index)
{
for (const ON_SubDFace* f = (const ON_SubDFace*)NextElement(); nullptr != f; f = (const ON_SubDFace*)NextElement())
{
if (ON_UNSET_UINT_INDEX != (&f->m_id)[1] && level_index == f->SubdivisionLevel())
return f;
}
return nullptr;
}
const ON_SubDFace* ON_SubDFaceIdIterator::CurrentFace() const
{
return (const ON_SubDFace*)CurrentElement();
};
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDVertexIterator
//
void ON_SubDVertexIterator::Internal_Init(
const ON_SubDRef& subd_ref,
unsigned int vertex_count,
const ON_SubDVertex* first,
const ON_SubDVertex* last,
ON_SubDComponentPtr component_ptr
)
{
m_subd_ref = subd_ref;
if (nullptr != first && nullptr != last && vertex_count > 0)
{
m_v_first = first;
m_v_last = last;
m_v_current = m_v_first;
m_vertex_count = vertex_count;
m_component_ptr
= (ON_SubDComponentPtr::Type::Unset == component_ptr.ComponentType())
? ON_SubDComponentPtr::Null
: component_ptr;
}
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubD& subd
)
{
const ON_SubDLevel& level = subd.ActiveLevel();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_vertex_count,
level.m_vertex[0],
level.m_vertex[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubD& subd,
unsigned level_index
)
{
const ON_SubDLevel& level = subd.LevelForExperts(level_index);
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_vertex_count,
level.m_vertex[0],
level.m_vertex[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubDRef& subd_ref
)
{
const ON_SubDLevel& level = subd_ref.SubD().ActiveLevel();
Internal_Init(
subd_ref,
level.m_vertex_count,
level.m_vertex[0],
level.m_vertex[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const ON_SubD& subd,
const ON_SubDVertex& vertex
)
{
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
1,
&vertex,
&vertex,
ON_SubDComponentPtr::Null
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const ON_SubDRef& subd_ref,
const ON_SubDVertex& vertex
)
{
Internal_Init(
subd_ref,
1,
&vertex,
&vertex,
ON_SubDComponentPtr::Null
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubD& subd,
const class ON_SubDEdge& edge
)
{
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
2,
edge.Vertex(0),
edge.Vertex(1),
ON_SubDComponentPtr::Create(&edge)
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDEdge& edge
)
{
Internal_Init(
subd_ref,
2,
edge.Vertex(0),
edge.Vertex(1),
ON_SubDComponentPtr::Create(&edge)
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubD& subd,
const class ON_SubDFace& face
)
{
const unsigned int vertex_count = face.EdgeCount();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
vertex_count,
face.Vertex(0),
face.Vertex(vertex_count-1),
ON_SubDComponentPtr::Create(&face)
);
}
ON_SubDVertexIterator::ON_SubDVertexIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDFace& face
)
{
const unsigned int vertex_count = face.EdgeCount();
Internal_Init(
subd_ref,
vertex_count,
face.Vertex(0),
face.Vertex(vertex_count-1),
ON_SubDComponentPtr::Create(&face)
);
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDVertexIterator::ON_SubDVertexIterator( ON_SubDVertexIterator&& src) ON_NOEXCEPT
: m_subd_ref(std::move(src.m_subd_ref))
, m_v_first(src.m_v_first)
, m_v_last(src.m_v_last)
, m_v_current(src.m_v_current)
, m_vertex_index(src.m_vertex_index)
, m_vertex_count(src.m_vertex_count)
, m_component_ptr(src.m_component_ptr)
{}
// rvalue assignment operator
ON_SubDVertexIterator& ON_SubDVertexIterator::operator=(ON_SubDVertexIterator&& src)
{
m_subd_ref.Clear();
m_subd_ref = std::move(src.m_subd_ref);
m_v_first = src.m_v_first;
m_v_last = src.m_v_last;
m_v_current = src.m_v_current;
m_vertex_index = src.m_vertex_index;
m_vertex_count = src.m_vertex_count;
m_component_ptr = src.m_component_ptr;
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDEdgeIterator
//
void ON_SubDEdgeIterator::Internal_Init(
const ON_SubDRef& subd_ref,
unsigned int edge_count,
const ON_SubDEdge* first,
const ON_SubDEdge* last,
ON_SubDComponentPtr component_ptr
)
{
m_subd_ref = subd_ref;
if (nullptr != first && nullptr != last && edge_count > 0)
{
m_e_first = first;
m_e_last = last;
m_e_current = m_e_first;
m_edge_count = edge_count;
m_component_ptr
= (ON_SubDComponentPtr::Type::Unset == component_ptr.ComponentType())
? ON_SubDComponentPtr::Null
: component_ptr;
}
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubD& subd
)
{
const ON_SubDLevel& level = subd.ActiveLevel();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_edge_count,
level.m_edge[0],
level.m_edge[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubD& subd,
unsigned level_index
)
{
const ON_SubDLevel& level = subd.LevelForExperts(level_index);
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_edge_count,
level.m_edge[0],
level.m_edge[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubDRef& subd_ref
)
{
const ON_SubDLevel& level = subd_ref.SubD().ActiveLevel();
Internal_Init(
subd_ref,
level.m_edge_count,
level.m_edge[0],
level.m_edge[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const ON_SubD& subd,
const ON_SubDEdge& edge
)
{
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
1,
&edge,
&edge,
ON_SubDComponentPtr::Null
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const ON_SubDRef& subd_ref,
const ON_SubDEdge& edge
)
{
Internal_Init(
subd_ref,
1,
&edge,
&edge,
ON_SubDComponentPtr::Null
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubD& subd,
const class ON_SubDVertex& vertex
)
{
const unsigned int edge_count = vertex.EdgeCount();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
edge_count,
vertex.Edge(0),
vertex.Edge(edge_count - 1),
ON_SubDComponentPtr::Create(&vertex)
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDVertex& vertex
)
{
const unsigned int edge_count = vertex.EdgeCount();
Internal_Init(
subd_ref,
edge_count,
vertex.Edge(0),
vertex.Edge(edge_count - 1),
ON_SubDComponentPtr::Create(&vertex)
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubD& subd,
const class ON_SubDFace& face
)
{
const unsigned int edge_count = face.EdgeCount();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
edge_count,
face.Edge(0),
face.Edge(edge_count - 1),
ON_SubDComponentPtr::Create(&face)
);
}
ON_SubDEdgeIterator::ON_SubDEdgeIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDFace& face
)
: m_subd_ref(subd_ref)
{
const unsigned int edge_count = face.EdgeCount();
Internal_Init(
subd_ref,
edge_count,
face.Edge(0),
face.Edge(edge_count - 1),
ON_SubDComponentPtr::Create(&face)
);
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDEdgeIterator::ON_SubDEdgeIterator( ON_SubDEdgeIterator&& src) ON_NOEXCEPT
: m_subd_ref(std::move(src.m_subd_ref))
, m_e_first(src.m_e_first)
, m_e_last(src.m_e_last)
, m_e_current(src.m_e_current)
, m_edge_index(src.m_edge_index)
, m_edge_count(src.m_edge_count)
, m_component_ptr(src.m_component_ptr)
{}
// rvalue assignment operator
ON_SubDEdgeIterator& ON_SubDEdgeIterator::operator=(ON_SubDEdgeIterator&& src)
{
m_subd_ref.Clear();
m_subd_ref = std::move(src.m_subd_ref);
m_e_first = src.m_e_first;
m_e_last = src.m_e_last;
m_e_current = src.m_e_current;
m_edge_index = src.m_edge_index;
m_edge_count = src.m_edge_count;
m_component_ptr = src.m_component_ptr;
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDFaceIterator
//
void ON_SubDFaceIterator::Internal_Init(
const ON_SubDRef& subd_ref,
unsigned int face_count,
const ON_SubDFace* first,
const ON_SubDFace* last,
ON_SubDComponentPtr component_ptr
)
{
m_subd_ref = subd_ref;
if (nullptr != first && nullptr != last && face_count > 0)
{
m_face_first = first;
m_face_last = last;
m_face_current = m_face_first;
m_face_count = face_count;
m_component_ptr
= (ON_SubDComponentPtr::Type::Unset == component_ptr.ComponentType())
? ON_SubDComponentPtr::Null
: component_ptr;
}
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const ON_SubD& subd
)
{
const ON_SubDLevel& level = subd.ActiveLevel();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_face_count,
level.m_face[0],
level.m_face[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const class ON_SubD& subd,
unsigned level_index
)
{
const ON_SubDLevel& level = subd.LevelForExperts(level_index);
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
level.m_face_count,
level.m_face[0],
level.m_face[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const ON_SubDRef& subd_ref
)
{
const ON_SubDLevel& level = subd_ref.SubD().ActiveLevel();
Internal_Init(
subd_ref,
level.m_face_count,
level.m_face[0],
level.m_face[1],
ON_SubDComponentPtr::Null
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const ON_SubD& subd,
const ON_SubDFace& face
)
{
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
1,
&face,
&face,
ON_SubDComponentPtr::Null
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const ON_SubDRef& subd_ref,
const ON_SubDFace& face
)
{
Internal_Init(
subd_ref,
1,
&face,
&face,
ON_SubDComponentPtr::Null
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const class ON_SubD& subd,
const class ON_SubDVertex& vertex
)
{
const unsigned int face_count = vertex.FaceCount();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
face_count,
vertex.Face(0),
vertex.Face(face_count - 1),
ON_SubDComponentPtr::Create(&vertex)
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDVertex& vertex
)
{
const unsigned int face_count = vertex.FaceCount();
Internal_Init(
subd_ref,
face_count,
vertex.Face(0),
vertex.Face(face_count - 1),
ON_SubDComponentPtr::Create(&vertex)
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const class ON_SubD& subd,
const class ON_SubDEdge& edge
)
{
const unsigned int face_count = edge.FaceCount();
Internal_Init(
ON_SubDRef::CreateReferenceForExperts(subd),
face_count,
edge.Face(0),
edge.Face(face_count - 1),
ON_SubDComponentPtr::Create(&edge)
);
}
ON_SubDFaceIterator::ON_SubDFaceIterator(
const class ON_SubDRef& subd_ref,
const class ON_SubDEdge& edge
)
{
const unsigned int face_count = edge.FaceCount();
Internal_Init(
subd_ref,
face_count,
edge.Face(0),
edge.Face(face_count - 1),
ON_SubDComponentPtr::Create(&edge)
);
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDFaceIterator::ON_SubDFaceIterator( ON_SubDFaceIterator&& src) ON_NOEXCEPT
: m_subd_ref(std::move(src.m_subd_ref))
, m_face_first(src.m_face_first)
, m_face_last(src.m_face_last)
, m_face_current(src.m_face_current)
, m_face_index(src.m_face_index)
, m_face_count(src.m_face_count)
, m_component_ptr(src.m_component_ptr)
{}
// rvalue assignment operator
ON_SubDFaceIterator& ON_SubDFaceIterator::operator=(ON_SubDFaceIterator&& src)
{
m_subd_ref.Clear();
m_subd_ref = std::move(src.m_subd_ref);
m_face_first = src.m_face_first;
m_face_last = src.m_face_last;
m_face_current = src.m_face_current;
m_face_index = src.m_face_index;
m_face_count = src.m_face_count;
m_component_ptr = src.m_component_ptr;
return *this;
}
#endif
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDFaceEdgeIterator
//
ON_SubDFaceEdgeIterator::ON_SubDFaceEdgeIterator()
: m_face(nullptr)
, m_edge_count(0)
, m_edge_index0(0)
, m_edge_index(0)
{}
ON_SubDFaceEdgeIterator::ON_SubDFaceEdgeIterator(
const ON_SubDFace* face
)
: m_face(nullptr)
, m_edge_count(0)
, m_edge_index0(0)
, m_edge_index(0)
{
Initialize(face, nullptr);
}
ON_SubDFaceEdgeIterator::ON_SubDFaceEdgeIterator(
const ON_SubDFace* face,
const ON_SubDEdge* first_edge
)
: m_face(nullptr)
, m_edge_count(0)
, m_edge_index0(0)
, m_edge_index(0)
{
Initialize(face, first_edge);
}
unsigned int ON_SubDFaceEdgeIterator::Initialize(
const ON_SubDFace* face
)
{
return Initialize(face, nullptr);
}
unsigned int ON_SubDFaceEdgeIterator::Initialize(
const ON_SubDFace* face,
const ON_SubDEdge* first_edge
)
{
m_face = face;
m_edge_count = (nullptr != face) ? face->m_edge_count : 0;
if (m_edge_count > 0 && nullptr != first_edge)
{
m_edge_index0 = face->EdgeArrayIndex(first_edge);
if (ON_UNSET_UINT_INDEX == m_edge_index0)
{
m_edge_count = 0;
m_edge_index0 = 0;
}
}
else
{
m_edge_index0 = 0;
}
m_edge_index = m_edge_index0;
return m_edge_count;
}
unsigned int ON_SubDFaceEdgeIterator::EdgeCount() const
{
return m_edge_count;
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::FirstEdge()
{
m_edge_index = m_edge_index0;
return CurrentEdge();
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::CurrentEdge() const
{
return (nullptr != m_face) ? m_face->Edge(m_edge_index) : nullptr;
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::NextEdge()
{
if (m_edge_count > 0)
{
m_edge_index = (m_edge_index + 1) % m_edge_count;
return CurrentEdge();
}
return nullptr;
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::PrevEdge()
{
if (m_edge_count > 0)
{
m_edge_index = (m_edge_index + (m_edge_count - 1)) % m_edge_count;
return CurrentEdge();
}
return nullptr;
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::NextEdge(bool bReturnNullAtFirstEdge)
{
if (m_edge_count > 0)
{
const unsigned int next_edge_index = (m_edge_index + 1) % m_edge_count;
if (bReturnNullAtFirstEdge && next_edge_index == m_edge_index0)
return nullptr;
m_edge_index = next_edge_index;
return CurrentEdge();
}
return nullptr;
}
const ON_SubDEdge* ON_SubDFaceEdgeIterator::PrevEdge(bool bReturnNullAtFirstEdge)
{
if (m_edge_count > 0)
{
const unsigned int prev_edge_index = (m_edge_index + (m_edge_count - 1)) % m_edge_count;
if (bReturnNullAtFirstEdge && prev_edge_index == m_edge_index0)
return nullptr;
m_edge_index = prev_edge_index;
return CurrentEdge();
}
return nullptr;
}
unsigned int ON_SubDFaceEdgeIterator::FirstEdgeIndex() const
{
return m_edge_index0;
}
unsigned int ON_SubDFaceEdgeIterator::CurrentEdgeIndex() const
{
return m_edge_index;
}
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDSectorId
//
const ON_SubDSectorId ON_SubDSectorId::Create(
const ON_SubDVertex* vertex,
const ON_SubDFace* face
)
{
ON_SubDSectorId sid;
if (nullptr == face && nullptr != vertex && vertex->IsSingleSectorVertex())
face = vertex->Face(0);
if (nullptr == vertex || nullptr == face)
{
// Creation of ON_SubDSectorId::Invalid in opennurbs_statics.cpp or
// just another invalid input.
sid.m_vertex_id = 0;
sid.m_minimum_face_id = 0;
sid.m_sector_face_count = 0xFFFFFFFFU;
return sid;
}
for (;;)
{
if (vertex->m_id <= 0 || vertex->m_id >= ON_UNSET_UINT_INDEX)
break;
if (face->m_id <= 0 || face->m_id >= ON_UNSET_UINT_INDEX)
break;
if (face->m_edge_count < 3)
break;
if (vertex->m_edge_count < 2)
break;
if (vertex->m_face_count < 1)
break;
const unsigned face_vi = face->VertexIndex(vertex);
if (face_vi >= face->m_edge_count)
break;
sid.m_vertex_id = vertex->m_id;
sid.m_minimum_face_id = face->m_id;
const unsigned short n = vertex->m_face_count;
unsigned short crease_face_count = 0;
unsigned int expected_crease_count = 0;
if (vertex->IsSmoothOrDart())
{
if (n < 2 || n != vertex->m_edge_count)
break;
const bool bIsDart = vertex->IsDart();
crease_face_count = bIsDart ? 2 : 0;
expected_crease_count = bIsDart ? 1 : 0;
}
else if ( vertex->IsCreaseOrCorner())
{
const ON_SubDComponentPtrPair pair
= (n + 1 == vertex->m_edge_count && 2==vertex->CreasedEdgeCount(true,true,true,false))
? vertex->BoundaryEdgePair()
: ON_SubDComponentPtrPair::Null;
if (pair.BothAreNotNull())
{
// we can avoid using a sector iterator
const ON_SubDEdge* e[2] = { pair.First().Edge(),pair.Second().Edge() };
if (nullptr == e[0] || nullptr == e[1])
break;
if (1 != e[0]->m_face_count || 1 != e[1]->m_face_count)
break;
crease_face_count = 1;
expected_crease_count = 2;
}
else
{
if (vertex->IsCrease())
{
if (n != vertex->m_edge_count)
return ON_SubDSectorId::Invalid;
}
// complicated case needs to use more time consuming sector iterator
ON_SubDSectorIterator sit0;
if ( vertex != sit0.Initialize(face, 0, face_vi))
return ON_SubDSectorId::Invalid;
ON_SubDSectorIterator sit1(sit0);
// advance sit0 until we hit a crease;
sid.m_sector_face_count = 1;
for (const ON_SubDFace* f = sit0.NextFace(ON_SubDSectorIterator::StopAt::AnyCrease); nullptr != f && sid.m_sector_face_count <= vertex->m_face_count; f = sit0.NextFace(ON_SubDSectorIterator::StopAt::AnyCrease))
{
++sid.m_sector_face_count;
if (f->m_id < sid.m_minimum_face_id)
sid.m_minimum_face_id = f->m_id;
}
// advance sit1 until we hit a crease;
for (const ON_SubDFace* f = sit1.PrevFace(ON_SubDSectorIterator::StopAt::AnyCrease); nullptr != f && sid.m_sector_face_count <= vertex->m_face_count; f = sit1.PrevFace(ON_SubDSectorIterator::StopAt::AnyCrease))
{
++sid.m_sector_face_count;
if (f->m_id < sid.m_minimum_face_id)
sid.m_minimum_face_id = f->m_id;
}
break;
}
}
else
{
break;
}
if (0 == sid.m_sector_face_count)
{
// we can avoid expensive sector iterator.
unsigned int crease_count = 0;
const ON_SubDFace* f;
for (unsigned short vei = 0; vei < vertex->m_edge_count; ++vei)
{
const ON_SubDEdge* e = ON_SUBD_EDGE_POINTER(vertex->m_edges[vei].m_ptr);
if (nullptr == e || 0 == e->m_face_count)
return ON_SubDSectorId::Invalid;
f = ON_SUBD_FACE_POINTER(e->m_face2[0].m_ptr);
if (nullptr == f)
return ON_SubDSectorId::Invalid;
if (f->m_id < sid.m_minimum_face_id)
sid.m_minimum_face_id = f->m_id;
if (ON_SubDEdgeTag::Crease == e->m_edge_tag)
{
++crease_count;
if (crease_count > expected_crease_count)
return ON_SubDSectorId::Invalid;
if (crease_face_count != e->m_face_count)
return ON_SubDSectorId::Invalid;
if (1 == crease_face_count)
continue;
}
if (2 != e->m_face_count)
return ON_SubDSectorId::Invalid;
f = ON_SUBD_FACE_POINTER(e->m_face2[1].m_ptr);
if (nullptr == f)
return ON_SubDSectorId::Invalid;
if (f->m_id < sid.m_minimum_face_id)
sid.m_minimum_face_id = f->m_id;
}
if (crease_count == expected_crease_count)
sid.m_sector_face_count = n;
}
break;
}
return (sid.IsSet() && sid.m_sector_face_count <= vertex->m_face_count) ? sid : ON_SubDSectorId::Invalid;
}
const ON_SubDSectorId ON_SubDSectorId::CreateFromIds(
unsigned int vertex_id,
unsigned int minimum_face_id
)
{
ON_SubDSectorId sid;
sid.m_vertex_id = vertex_id;
sid.m_minimum_face_id = minimum_face_id;
sid.m_sector_face_count = 0;
return sid;
}
int ON_SubDSectorId::Compare(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
if (lhs.m_vertex_id < rhs.m_vertex_id)
return -1;
if (lhs.m_vertex_id > rhs.m_vertex_id)
return 1;
if (lhs.m_minimum_face_id < rhs.m_minimum_face_id)
return -1;
if (lhs.m_minimum_face_id > rhs.m_minimum_face_id)
return 1;
if (lhs.m_sector_face_count < rhs.m_sector_face_count)
return -1;
if (lhs.m_sector_face_count > rhs.m_sector_face_count)
return 1;
return 0;
}
int ON_SubDSectorId::CompareFromPointers(const ON_SubDSectorId* lhs, const ON_SubDSectorId* rhs)
{
if (nullptr == lhs || nullptr == rhs)
{
// sort nullptr to end
if (nullptr != lhs)
return -1;
if (nullptr != rhs)
return 1;
return 0;
}
return ON_SubDSectorId::Compare(*lhs, *rhs);
}
const unsigned int ON_SubDSectorId::VertexId() const
{
return m_vertex_id;
}
const unsigned int ON_SubDSectorId::MinimumFaceId() const
{
return m_minimum_face_id;
}
const unsigned int ON_SubDSectorId::SectorFaceCount() const
{
return m_sector_face_count <= 0x10000U ? m_sector_face_count : 0U;
}
bool ON_SubDSectorId::IsZero() const
{
return 0 == m_vertex_id && 0 == m_minimum_face_id && 0 == m_sector_face_count;
}
bool ON_SubDSectorId::IsSet() const
{
// the maximum valid subd vertex face count is 0xFFFF.
return m_vertex_id > 0 && m_minimum_face_id > 0 && m_sector_face_count > 0 && m_vertex_id < ON_UNSET_UINT_INDEX&& m_minimum_face_id < ON_UNSET_UINT_INDEX&& m_sector_face_count < 0x10000U;
}
bool operator==(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return 0 == ON_SubDSectorId::Compare(lhs, rhs);
}
bool operator!=(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return 0 != ON_SubDSectorId::Compare(lhs, rhs);
}
bool operator>(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return ON_SubDSectorId::Compare(lhs, rhs) < 0;
}
bool operator<(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return ON_SubDSectorId::Compare(lhs, rhs) > 0;
}
bool operator>=(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return ON_SubDSectorId::Compare(lhs, rhs) >= 0;
}
bool operator<=(ON_SubDSectorId lhs, ON_SubDSectorId rhs)
{
return ON_SubDSectorId::Compare(lhs, rhs) <= 0;
}
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDSectorIterator
//
static ON_SubDSectorIterator ON_SectorIterator_EmptyInitialize()
{
ON_SubDSectorIterator empty_init;
empty_init.Initialize();
return empty_init;
}
const ON_SubDSectorIterator ON_SubDSectorIterator::Empty(ON_SectorIterator_EmptyInitialize());
void ON_SubDSectorIterator::Initialize()
{
// apply in place construction to this
new (this) ON_SubDSectorIterator();
m_current_eptr[0] = ON_SubDEdgePtr::Null;
m_current_eptr[1] = ON_SubDEdgePtr::Null;
m_current_fei[0] = 0;
m_current_fei[1] = 0;
}
const ON_SubDVertex* ON_SubDSectorIterator::Initialize(
const ON_SubDVertex* center_vertex
)
{
Initialize();
if (nullptr == center_vertex || 0 == center_vertex->m_face_count || nullptr == center_vertex->m_faces)
return ON_SUBD_RETURN_ERROR(nullptr);
ON__UINT_PTR initial_face_direction = 0;
return Initialize(center_vertex->m_faces[0], initial_face_direction, center_vertex);
}
const ON_SubDVertex* ON_SubDSectorIterator::Initialize(
const ON_SubDFace* initial_face,
ON__UINT_PTR iterator_orientation,
const ON_SubDVertex* center_vertex
)
{
if (nullptr != center_vertex && nullptr != initial_face)
{
ON__UINT_PTR eptr;
const ON_SubDEdge* edge;
const unsigned int edge_count = initial_face->m_edge_count;
const ON_SubDEdgePtr* face_eptr = initial_face->m_edge4;
for (unsigned int efi = 0; efi < edge_count; efi++, face_eptr++)
{
if (4 == efi)
{
face_eptr = initial_face->m_edgex;
if (nullptr == face_eptr)
break;
}
eptr = face_eptr->m_ptr;
edge = ON_SUBD_EDGE_POINTER(eptr);
if (nullptr == edge)
continue;
eptr = ON_SUBD_EDGE_DIRECTION(eptr);
if (center_vertex == edge->m_vertex[eptr])
return Initialize(initial_face, iterator_orientation, efi);
}
}
Initialize();
return ON_SUBD_RETURN_ERROR(nullptr);
}
const ON_SubDVertex* ON_SubDSectorIterator::Initialize(
const ON_SubDFace* initial_face,
ON__UINT_PTR iterator_orientation,
unsigned int face_vertex_index
)
{
Initialize();
for (;;)
{
if (nullptr == initial_face)
break;
if (0 != iterator_orientation && 1 != iterator_orientation)
break;
const unsigned int face_edge_count = initial_face->m_edge_count;
if (face_vertex_index >= face_edge_count)
break;
m_initial_face = initial_face;
m_initial_fvi = face_vertex_index;
// initial_face->Edge(face_vertex_index) = edge "leaving" the center vertex
ON_SubDEdgePtr eptr;
if (face_vertex_index < 4)
{
eptr = initial_face->m_edge4[face_vertex_index];
}
else
{
if (nullptr == initial_face->m_edgex)
return ON_SUBD_RETURN_ERROR(nullptr);
eptr = initial_face->m_edgex[face_vertex_index - 4];
}
const ON_SubDEdge* edge0 = ON_SUBD_EDGE_POINTER(eptr.m_ptr);
if (nullptr == edge0)
break;
// m_current_eptr[0] = "prev" side edge
m_current_fei[0] = face_vertex_index;
m_current_eptr[0] = eptr;
// back up one vertex on the face
face_vertex_index = (face_vertex_index+face_edge_count-1) % face_edge_count;
// initial_face->Edge(face_vertex_index) = edge "entering" the center vertex
if (face_vertex_index < 4)
{
eptr = initial_face->m_edge4[face_vertex_index];
}
else
{
if (nullptr == initial_face->m_edgex)
return ON_SUBD_RETURN_ERROR(nullptr);
eptr = initial_face->m_edgex[face_vertex_index - 4];
}
const ON_SubDEdge* edge1 = ON_SUBD_EDGE_POINTER(eptr.m_ptr);
if (nullptr == edge1)
break;
// m_current_eptr[1] = "next" side edge
m_current_fei[1] = face_vertex_index;
m_current_eptr[1] = eptr.Reversed(); // (reversed because face's eptr ends at center vertex)
const ON_SubDVertex* center_vertex0 = edge0->m_vertex[ON_SUBD_EDGE_DIRECTION(m_current_eptr[0].m_ptr)];
const ON_SubDVertex* center_vertex1 = edge1->m_vertex[ON_SUBD_EDGE_DIRECTION(m_current_eptr[1].m_ptr)];
if (center_vertex0 != center_vertex1)
{
if (nullptr == center_vertex0)
m_center_vertex = center_vertex1;
else if ( nullptr == center_vertex1)
m_center_vertex = center_vertex0;
else
break;
}
else if (nullptr != center_vertex0)
m_center_vertex = center_vertex0;
else
break;
if (1 == iterator_orientation)
{
m_initial_face_dir = 1;
unsigned int i = m_current_fei[0];
m_current_fei[0] = m_current_fei[1];
m_current_fei[1] = i;
eptr = m_current_eptr[0];
m_current_eptr[0] = m_current_eptr[1];
m_current_eptr[1] = eptr;
}
m_current_face = m_initial_face;
m_current_face_dir = m_initial_face_dir;
m_current_fvi = m_initial_fvi;
#if defined(ON_DEBUG)
IsValid();
#endif
return m_center_vertex;
}
Initialize();
return ON_SUBD_RETURN_ERROR(nullptr);
}
const ON_SubDFace* ON_SubDSectorIterator::FirstFace()
{
if (nullptr == m_initial_face)
Initialize();
else
Initialize(m_initial_face, m_initial_face_dir, m_initial_fvi);
return m_initial_face;
}
bool ON_SubDSectorIterator::IsValid() const
{
if (nullptr == m_center_vertex && nullptr == m_initial_face)
return true;
if (nullptr == m_center_vertex || nullptr == m_initial_face)
return ON_SUBD_RETURN_ERROR(false);
if ( m_center_vertex != m_initial_face->Vertex(m_initial_fvi) )
return ON_SUBD_RETURN_ERROR(false);
if (nullptr == m_current_face)
return true; // finished iterating
if (m_center_vertex != m_current_face->Vertex(m_current_fvi))
return ON_SUBD_RETURN_ERROR(false);
const ON_SubDEdge* edge[2] = { m_current_eptr[0].Edge(), m_current_eptr[1].Edge() };
if (nullptr == edge[0] || nullptr == edge[1])
return ON_SUBD_RETURN_ERROR(false);
if (m_center_vertex != edge[0]->m_vertex[ON_SUBD_EDGE_DIRECTION(m_current_eptr[0].m_ptr)])
return ON_SUBD_RETURN_ERROR(false);
if (m_center_vertex != edge[1]->m_vertex[ON_SUBD_EDGE_DIRECTION(m_current_eptr[1].m_ptr)])
return ON_SUBD_RETURN_ERROR(false);
const ON_SubDEdgePtr feptr[2] = { m_current_face->EdgePtr(m_current_fei[0]), m_current_face->EdgePtr(m_current_fei[1]) };
if (edge[0] != ON_SUBD_EDGE_POINTER(feptr[0].m_ptr))
return ON_SUBD_RETURN_ERROR(false);
if (edge[1] != ON_SUBD_EDGE_POINTER(feptr[1].m_ptr))
return ON_SUBD_RETURN_ERROR(false);
return true;
}
const ON_SubDVertex* ON_SubDSectorIterator::CenterVertex() const
{
return m_center_vertex;
}
const ON_SubDFace* ON_SubDSectorIterator::InitialFace() const
{
return m_initial_face;
}
int ON_SubDSectorIterator::CurrentRingIndex() const
{
return m_current_ring_index;
}
const ON_SubDFace* ON_SubDSectorIterator::CurrentFace() const
{
return m_current_face;
}
ON_SubDFacePtr ON_SubDSectorIterator::CurrentFacePtr() const
{
return ON_SubDFacePtr::Create(m_current_face,m_current_face_dir);
}
unsigned int ON_SubDSectorIterator::InitialFaceCenterVertexIndex() const
{
return m_initial_fvi;
}
unsigned int ON_SubDSectorIterator::CurrentFaceCenterVertexIndex() const
{
return m_current_fvi;
}
unsigned int ON_SubDSectorIterator::CurrentFaceDirection() const
{
return m_current_face_dir;
}
ON_SubDEdgePtr ON_SubDSectorIterator::CurrentEdgePtr(
unsigned int face_side_index
) const
{
return (face_side_index < 2) ? m_current_eptr[face_side_index] : ON_SubDEdgePtr::Null;
}
const ON_SubDEdge* ON_SubDSectorIterator::CurrentEdge(
unsigned int face_side_index
) const
{
return (face_side_index < 2) ? ON_SUBD_EDGE_POINTER(m_current_eptr[face_side_index].m_ptr) : nullptr;
}
ON__UINT_PTR ON_SubDSectorIterator::CurrentEdgeDirection(
unsigned int face_side_index
) const
{
return (face_side_index < 2) ? ON_SUBD_EDGE_DIRECTION(m_current_eptr[face_side_index].m_ptr) : 0;
}
const ON_SubDVertex* ON_SubDSectorIterator::CurrentEdgeRingVertex(
unsigned int face_side_index
) const
{
if (face_side_index >= 2)
return ON_SUBD_RETURN_ERROR(nullptr);
ON__UINT_PTR eptr = m_current_eptr[face_side_index].m_ptr;
const ON_SubDEdge* edge = ON_SUBD_EDGE_POINTER(eptr);
if (nullptr == edge)
return ON_SUBD_RETURN_ERROR(nullptr);
const ON_SubDVertex* edge_ring_vertex = edge->m_vertex[1 - ON_SUBD_EDGE_DIRECTION(eptr)];
if ( nullptr == edge_ring_vertex || edge_ring_vertex == m_center_vertex)
return ON_SUBD_RETURN_ERROR(nullptr);
return edge_ring_vertex;
}
const ON_SubDFace* ON_SubDSectorIterator::NextFace(
ON_SubDSectorIterator::StopAt stop_at
)
{
return IncrementFace(1, stop_at);
}
const ON_SubDFace* ON_SubDSectorIterator::PrevFace(
ON_SubDSectorIterator::StopAt stop_at
)
{
return IncrementFace(-1, stop_at);
}
const ON_SubDFace* ON_SubDSectorIterator::IncrementFace(
int increment_direction,
ON_SubDSectorIterator::StopAt stop_at
)
{
if (nullptr == m_current_face)
{
return ON_SUBD_RETURN_ERROR(nullptr);
}
// increment_direction > 0 means counterclockwise / next
// increment_direction <= 0 means clockwise / prev
unsigned int side_index = (increment_direction > 0) ? 1 : 0;
ON__UINT_PTR eptr = m_current_eptr[side_index].m_ptr;
const ON_SubDEdge* edge = ON_SUBD_EDGE_POINTER(eptr);
if (nullptr == edge)
{
return ON_SUBD_RETURN_ERROR(nullptr);
}
for (;;)
{
if (edge->m_face_count != 2)
{
// set stop_at to something not equal to Boundary
stop_at = ON_SubDSectorIterator::StopAt::AnyCrease;
break;
}
if (ON_SubDSectorIterator::StopAt::Boundary != stop_at)
{
if (ON_SubDEdgeTag::Crease == edge->m_edge_tag)
{
if (ON_SubDSectorIterator::StopAt::AnyCrease == stop_at)
break;
if (ON_SubDSectorIterator::StopAt::HardCrease == stop_at && edge->IsHardCrease())
break;
}
stop_at = ON_SubDSectorIterator::StopAt::Boundary;
}
unsigned int efi;
if (m_current_face == ON_SUBD_FACE_POINTER(edge->m_face2[0].m_ptr))
{
efi = 0;
}
else if (m_current_face == ON_SUBD_FACE_POINTER(edge->m_face2[1].m_ptr))
{
efi = 1;
}
else
break;
const ON__UINT_PTR ef0dir = ON_SUBD_FACE_DIRECTION(edge->m_face2[efi].m_ptr);
efi = 1 - efi;
const ON__UINT_PTR ef1dir = ON_SUBD_FACE_DIRECTION(edge->m_face2[efi].m_ptr);
const ON_SubDFace* face1 = ON_SUBD_FACE_POINTER(edge->m_face2[efi].m_ptr);
if (nullptr == face1)
break;
const unsigned int face1_edge_count = face1->m_edge_count;
const ON_SubDEdgePtr* face1_edges = face1->m_edge4;
for (unsigned int fei = 0; fei < face1_edge_count; fei++, face1_edges++)
{
if (4 == fei)
{
if (nullptr == (face1_edges = face1->m_edgex))
break;
}
if (edge != ON_SUBD_EDGE_POINTER(face1_edges->m_ptr))
continue;
// At this point, face1->Edges(fei) is the edge I just hopped across
// to get from the old current face to face 1. Update current face
// information and return.
m_current_face = face1;
if (ef0dir == ef1dir)
m_current_face_dir = 1 - m_current_face_dir;
side_index = 1 - side_index;
m_current_fei[side_index] = fei;
if (m_center_vertex == edge->m_vertex[0])
m_current_eptr[side_index] = ON_SubDEdgePtr::Create(edge,0);
else if (m_center_vertex == edge->m_vertex[1])
m_current_eptr[side_index] = ON_SubDEdgePtr::Create(edge,1);
else
break;
if (side_index == m_current_face_dir)
{
m_current_fvi = fei;
fei = (fei > 0) ? (fei - 1) : (face1_edge_count - 1);
}
else
{
fei = (fei + 1) % face1_edge_count;
m_current_fvi = fei;
}
if (fei < 4)
face1_edges = face1->m_edge4;
else
{
if (nullptr == (face1_edges = face1->m_edgex))
break;
face1_edges -= 4;
}
side_index = 1 - side_index;
m_current_fei[side_index] = fei;
edge = ON_SUBD_EDGE_POINTER(face1_edges[fei].m_ptr);
if ( nullptr == edge)
break;
if (m_center_vertex == edge->m_vertex[0])
m_current_eptr[side_index] = ON_SubDEdgePtr::Create(edge,0);
else if (m_center_vertex == edge->m_vertex[1])
m_current_eptr[side_index] = ON_SubDEdgePtr::Create(edge,1);
else
break;
if (increment_direction > 0)
m_current_ring_index++;
else
m_current_ring_index--;
#if defined(ON_DEBUG)
IsValid();
#endif
return m_current_face;
}
break;
}
// termination
m_current_face = nullptr;
m_current_fvi = 0;
m_current_fei[0] = 0;
m_current_fei[1] = 0;
if (ON_SubDSectorIterator::StopAt::Boundary != stop_at)
{
// termination at a crease, nonmanifold edge, or edge with one face
m_current_eptr[1 - side_index] = m_current_eptr[side_index];
m_current_eptr[side_index] = ON_SubDEdgePtr::Null;
return nullptr;
}
// error condition
m_current_eptr[0] = ON_SubDEdgePtr::Null;
m_current_eptr[0] = ON_SubDEdgePtr::Null;
return ON_SUBD_RETURN_ERROR(nullptr);
}
const ON_SubDFace* ON_SubDSectorIterator::IncrementToCrease(
int increment_direction
)
{
const ON_SubDEdgeTag etag = this->IncrementToCrease(
increment_direction,
nullptr
);
return (ON_SubDEdgeTag::Crease == etag) ? this->CurrentFace() : nullptr;
}
ON_SubDEdgeTag ON_SubDSectorIterator::IncrementToCrease(
int increment_direction,
unsigned* increment_count
)
{
if (nullptr != increment_count)
*increment_count = 0;
if (nullptr == m_center_vertex)
return ON_SUBD_RETURN_ERROR(ON_SubDEdgeTag::Unset);
const unsigned int N = m_center_vertex->m_edge_count;
const unsigned int edge_side = increment_direction > 0 ? 1 : 0;
ON_SubDSectorIterator sit(*this);
const ON_SubDFace* face0 = sit.CurrentFace();
if (nullptr == face0)
return ON_SUBD_RETURN_ERROR(ON_SubDEdgeTag::Unset);
// The for (unsigned int i = 0; i < N; i++) {} prevents infinite looping
// if the topology is pointers contain an invalid cycle.
for (unsigned int i = 0; i < N; i++)
{
const ON_SubDEdge* edge = sit.CurrentEdge(edge_side);
if (nullptr == edge)
return ON_SUBD_RETURN_ERROR(ON_SubDEdgeTag::Unset);
if (edge->m_face_count != 2 || ON_SubDEdgeTag::Crease == edge->m_edge_tag)
{
if (nullptr != increment_count)
*increment_count = i;
*this = sit;
return ON_SubDEdgeTag::Crease;
}
const ON_SubDFace* face = sit.IncrementFace(increment_direction,ON_SubDSectorIterator::StopAt::AnyCrease);
if (nullptr == face)
return ON_SUBD_RETURN_ERROR(ON_SubDEdgeTag::Unset);
if ( face == face0 )
return ON_SubDEdgeTag::Smooth; // no crease and back where we started
}
return ON_SUBD_RETURN_ERROR(ON_SubDEdgeTag::Unset);
}
bool ON_SubDSectorIterator::InitializeToCurrentFace()
{
const ON_SubDFace* face = CurrentFace();
if ( nullptr == face)
return ON_SUBD_RETURN_ERROR(false);
ON_SubDSectorIterator sit;
if (nullptr == sit.Initialize(face, sit.CurrentFaceDirection(), sit.CurrentFaceCenterVertexIndex()))
return ON_SUBD_RETURN_ERROR(false);
if (face != sit.CurrentFace())
return ON_SUBD_RETURN_ERROR(false);
*this = sit;
return true;
}
//////////////////////////////////////////////////////////////////////////
//
// ON_SubDComponentIterator
//
ON_SubDComponentIterator::ON_SubDComponentIterator(
const class ON_SubD& subd
)
{
*this = ON_SubDComponentIterator(ON_SubDRef::CreateReferenceForExperts(subd));
}
ON_SubDComponentIterator::ON_SubDComponentIterator(
const class ON_SubDRef& subd_ref
)
{
m_subd_ref = subd_ref;
const ON_SubDLevel& level = subd_ref.SubD().ActiveLevel();
const ON_SubDFace* f_first = level.m_face[0];
const ON_SubDFace* f_last = level.m_face[1];
if (f_first && f_last)
{
m_face_first = f_first;
m_face_last = f_last;
m_cptr_current = ON_SubDComponentPtr::Create(m_face_first);
}
const ON_SubDEdge* e_first = level.m_edge[0];
const ON_SubDEdge* e_last = level.m_edge[1];
if (e_first && e_last)
{
m_edge_first = e_first;
m_edge_last = e_last;
m_cptr_current = ON_SubDComponentPtr::Create(m_edge_first);
}
const ON_SubDVertex* v_first = level.m_vertex[0];
const ON_SubDVertex* v_last = level.m_vertex[1];
if (v_first && v_last)
{
m_vertex_first = v_first;
m_vertex_last = v_last;
m_cptr_current = ON_SubDComponentPtr::Create(m_vertex_first);
}
}
#if defined(ON_HAS_RVALUEREF)
// rvalue copy constructor
ON_SubDComponentIterator::ON_SubDComponentIterator( ON_SubDComponentIterator&& src) ON_NOEXCEPT
: m_subd_ref(std::move(src.m_subd_ref))
, m_subd_level(src.m_subd_level)
, m_vertex_first(src.m_vertex_first)
, m_vertex_last(src.m_vertex_last)
, m_edge_first(src.m_edge_first)
, m_edge_last(src.m_edge_last)
, m_face_first(src.m_face_first)
, m_face_last(src.m_face_last)
, m_cptr_current(src.m_cptr_current)
{}
// rvalue assignment operator
ON_SubDComponentIterator& ON_SubDComponentIterator::operator=(ON_SubDComponentIterator&& src)
{
m_subd_ref.Clear();
m_subd_ref = std::move(src.m_subd_ref);
m_subd_level = src.m_subd_level;
m_vertex_first = src.m_vertex_first;
m_vertex_last = src.m_vertex_last;
m_edge_first = src.m_edge_first;
m_edge_last = src.m_edge_last;
m_face_first = src.m_face_first;
m_face_last = src.m_face_last;
m_cptr_current = src.m_cptr_current;
return *this;
}
#endif
/*
Description:
Set the iterator to the beginning of the component list.
Returns:
First component in the list.
*/
const class ON_SubDComponentPtr ON_SubDComponentIterator::FirstComponent()
{
if (nullptr != m_vertex_first)
m_cptr_current = ON_SubDComponentPtr::Create(m_vertex_first);
else if (nullptr != m_edge_first)
m_cptr_current = ON_SubDComponentPtr::Create(m_edge_first);
else if (nullptr != m_face_first)
m_cptr_current = ON_SubDComponentPtr::Create(m_face_first);
else
m_cptr_current = ON_SubDComponentPtr::Null;
return m_cptr_current;
}
const class ON_SubDComponentPtr ON_SubDComponentIterator::NextComponent()
{
switch (m_cptr_current.ComponentType())
{
case ON_SubDComponentPtr::Type::Vertex:
{
const ON_SubDVertex* vertex = ON_SUBD_VERTEX_POINTER(m_cptr_current.m_ptr);
if (nullptr != vertex && vertex != m_vertex_last && nullptr != vertex->m_next_vertex)
{
m_cptr_current = ON_SubDComponentPtr::Create(vertex->m_next_vertex);
return m_cptr_current;
}
}
m_cptr_current = ON_SubDComponentPtr::Null;
// no break here
case ON_SubDComponentPtr::Type::Edge:
{
if (0 == m_cptr_current.m_ptr && nullptr != m_edge_first)
{
// switching from vertex to edge
m_cptr_current = ON_SubDComponentPtr::Create(m_edge_first);
return m_cptr_current;
}
const ON_SubDEdge* edge = ON_SUBD_EDGE_POINTER(m_cptr_current.m_ptr);
if (nullptr != edge && edge != m_edge_last && nullptr != edge->m_next_edge )
{
m_cptr_current = ON_SubDComponentPtr::Create(edge->m_next_edge);
return m_cptr_current;
}
}
m_cptr_current = ON_SubDComponentPtr::Null;
// no break here
case ON_SubDComponentPtr::Type::Face:
{
if (0 == m_cptr_current.m_ptr && nullptr != m_face_first)
{
// switching from edge to face
m_cptr_current = ON_SubDComponentPtr::Create(m_face_first);
return m_cptr_current;
}
const ON_SubDFace* face = ON_SUBD_FACE_POINTER(m_cptr_current.m_ptr);
if (nullptr != face && face != m_face_last && nullptr != face->m_next_face)
{
m_cptr_current = ON_SubDComponentPtr::Create(face->m_next_face);
return m_cptr_current;
}
}
m_cptr_current = ON_SubDComponentPtr::Null;
break;
default:
break;
}
return m_cptr_current;
}
const class ON_SubDComponentPtr ON_SubDComponentIterator::LastComponent()
{
if (nullptr != m_face_last)
m_cptr_current = ON_SubDComponentPtr::Create(m_face_last);
else if (nullptr != m_edge_last)
m_cptr_current = ON_SubDComponentPtr::Create(m_edge_last);
else if (nullptr != m_vertex_last)
m_cptr_current = ON_SubDComponentPtr::Create(m_vertex_last);
else
m_cptr_current = ON_SubDComponentPtr::Null;
return m_cptr_current;
}