mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 19:46:08 +08:00
2144 lines
54 KiB
C++
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;
|
|
}
|