mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 03:26:09 +08:00
856 lines
21 KiB
C++
856 lines
21 KiB
C++
#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_polyedgecurve.h"
|
|
|
|
ON_OBJECT_IMPLEMENT(ON_PolyEdgeSegment,ON_CurveProxy,"42F47A87-5B1B-4e31-AB87-4639D78325D6");
|
|
|
|
ON_PolyEdgeSegment::ON_PolyEdgeSegment()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
ON_PolyEdgeSegment::~ON_PolyEdgeSegment()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
void ON_PolyEdgeSegment::Init()
|
|
{
|
|
m_component_index.UnSet();
|
|
m_object_id = ON_nil_uuid;
|
|
m_brep = 0;
|
|
m_trim = 0;
|
|
m_edge = 0;
|
|
m_face = 0;
|
|
m_surface = 0;
|
|
m_edge_domain = ON_Interval::EmptyInterval;
|
|
m_trim_domain = ON_Interval::EmptyInterval;
|
|
ON_CurveProxy::SetProxyCurve(0);
|
|
|
|
ClearEvalCacheHelper();
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::Create(
|
|
const ON_BrepTrim* trim,
|
|
const ON_UUID& object_id
|
|
)
|
|
{
|
|
Init();
|
|
if ( !trim )
|
|
return false;
|
|
if ( trim->m_ei >= 0 )
|
|
return false;
|
|
const ON_Brep* brep = trim->Brep();
|
|
if ( !brep )
|
|
return false;
|
|
const ON_BrepEdge* edge = trim->Edge();
|
|
if ( !edge )
|
|
return false;
|
|
const ON_Curve* c3 = edge->EdgeCurveOf();
|
|
if ( !c3 )
|
|
return false;
|
|
m_brep = brep;
|
|
m_trim = trim;
|
|
m_edge = edge;
|
|
m_face = trim->Face();
|
|
if ( m_face )
|
|
m_surface = m_face->SurfaceOf();
|
|
m_edge_domain = m_edge->Domain();
|
|
m_trim_domain = m_trim->Domain();
|
|
ON_CurveProxy::SetProxyCurve(
|
|
c3,
|
|
edge->ProxyCurveDomain()
|
|
);
|
|
if ( m_edge->ProxyCurveIsReversed() )
|
|
ON_CurveProxy::Reverse();
|
|
ON_CurveProxy::SetDomain( m_edge_domain[0], m_edge_domain[1] );
|
|
m_component_index = trim->ComponentIndex();
|
|
m_object_id = object_id;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool ON_PolyEdgeSegment::ReversedEdgeDir() const
|
|
{
|
|
bool rc = false;
|
|
if ( m_edge )
|
|
{
|
|
rc = m_edge->ProxyCurveIsReversed() != ON_CurveProxy::ProxyCurveIsReversed();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::ReversedTrimDir() const
|
|
{
|
|
bool rc = false;
|
|
if ( m_trim && m_edge )
|
|
{
|
|
rc = ReversedEdgeDir();
|
|
if ( m_trim->m_bRev3d )
|
|
rc = !rc;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::Create(
|
|
const ON_Curve* curve,
|
|
const ON_UUID& object_id
|
|
)
|
|
{
|
|
//bool rc = false;
|
|
Init();
|
|
if ( !curve )
|
|
return false;
|
|
const ON_BrepEdge* edge = ON_BrepEdge::Cast(curve);
|
|
if ( edge )
|
|
{
|
|
const ON_Brep* brep = edge->Brep();
|
|
if ( !brep )
|
|
return false;
|
|
const ON_Curve* c3 = edge->EdgeCurveOf();
|
|
if ( !c3 )
|
|
return false;
|
|
m_edge = edge;
|
|
m_brep = brep;
|
|
m_component_index = edge->ComponentIndex();
|
|
m_edge_domain = m_edge->Domain();
|
|
m_trim_domain = m_trim->Domain();
|
|
ON_CurveProxy::SetProxyCurve(
|
|
c3,
|
|
edge->ProxyCurveDomain()
|
|
);
|
|
if ( m_edge->ProxyCurveIsReversed() )
|
|
ON_CurveProxy::Reverse();
|
|
ON_CurveProxy::SetDomain( m_edge_domain[0], m_edge_domain[1] );
|
|
}
|
|
else
|
|
{
|
|
ON_CurveProxy::SetProxyCurve(const_cast<ON_Curve*>(curve));
|
|
}
|
|
m_object_id = object_id;
|
|
return true;
|
|
}
|
|
|
|
const ON_BrepEdge* ON_PolyEdgeSegment::BrepEdge() const
|
|
{
|
|
return m_edge;
|
|
}
|
|
|
|
const ON_BrepTrim* ON_PolyEdgeSegment::BrepTrim() const
|
|
{
|
|
return m_trim;
|
|
}
|
|
|
|
const ON_Brep* ON_PolyEdgeSegment::Brep() const
|
|
{
|
|
return m_brep;
|
|
}
|
|
|
|
const ON_BrepFace* ON_PolyEdgeSegment::BrepFace() const
|
|
{
|
|
return m_face;
|
|
}
|
|
|
|
const ON_Surface* ON_PolyEdgeSegment::Surface() const
|
|
{
|
|
return m_surface;
|
|
}
|
|
|
|
ON_Surface::ISO ON_PolyEdgeSegment::IsoType() const
|
|
{
|
|
return m_trim ? m_trim->m_iso : ON_Surface::not_iso;
|
|
}
|
|
|
|
ON_Interval ON_PolyEdgeSegment::EdgeDomain() const
|
|
{
|
|
return m_edge_domain;
|
|
}
|
|
|
|
ON_Interval ON_PolyEdgeSegment::TrimDomain() const
|
|
{
|
|
return m_trim_domain;
|
|
}
|
|
|
|
|
|
void ON_PolyEdgeSegment::ClearEvalCacheHelper()
|
|
{
|
|
m_t = ON_UNSET_VALUE;
|
|
m_edge_t = ON_UNSET_VALUE;
|
|
m_trim_t = ON_UNSET_VALUE;
|
|
m_srf_uv[0] = ON_UNSET_VALUE;
|
|
m_srf_uv[1] = ON_UNSET_VALUE;
|
|
m_trim_hint = 0;
|
|
m_edge_hint = 0;
|
|
m_evsrf_hint[0] = 0;
|
|
m_evsrf_hint[1] = 0;
|
|
m_evsrf_uv[0] = ON_UNSET_VALUE;
|
|
m_evsrf_uv[1] = ON_UNSET_VALUE;
|
|
m_evsrf_pt = ON_3dPoint::UnsetPoint;
|
|
}
|
|
|
|
|
|
double ON_PolyEdgeSegment::EdgeParameter(double t) const
|
|
{
|
|
double edge_t = ON_UNSET_VALUE;
|
|
if ( m_edge )
|
|
{
|
|
if ( m_t == t && m_edge_t != ON_UNSET_VALUE )
|
|
edge_t = m_edge_t;
|
|
else
|
|
{
|
|
ON_PolyEdgeSegment* p = const_cast<ON_PolyEdgeSegment*>(this);
|
|
if ( t != m_t )
|
|
{
|
|
p->m_t = t;
|
|
p->m_trim_t = ON_UNSET_VALUE;
|
|
p->m_srf_uv[0] = ON_UNSET_VALUE;
|
|
p->m_srf_uv[1] = ON_UNSET_VALUE;
|
|
}
|
|
ON_Interval d = Domain();
|
|
bool bReversedEdgeDir = ReversedEdgeDir();
|
|
if ( bReversedEdgeDir || m_edge_domain != d )
|
|
{
|
|
double s = d.NormalizedParameterAt(t);
|
|
if ( bReversedEdgeDir )
|
|
s = 1.0 - s;
|
|
edge_t = m_edge_domain.ParameterAt(s);
|
|
}
|
|
else
|
|
edge_t = t;
|
|
p->m_edge_t = edge_t;
|
|
}
|
|
}
|
|
return edge_t;
|
|
}
|
|
|
|
|
|
|
|
|
|
ON_OBJECT_IMPLEMENT(ON_PolyEdgeCurve,ON_PolyCurve,"39FF3DD3-FE0F-4807-9D59-185F0D73C0E4");
|
|
|
|
ON_PolyEdgeCurve::ON_PolyEdgeCurve()
|
|
{
|
|
}
|
|
|
|
ON_PolyEdgeCurve::~ON_PolyEdgeCurve()
|
|
{
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::SetStartPoint( ON_3dPoint start_point )
|
|
{
|
|
return ON_Curve::SetStartPoint(start_point); // cannot change edges
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::SetEndPoint( ON_3dPoint end_point )
|
|
{
|
|
return ON_Curve::SetEndPoint(end_point); // cannot change edges
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::ChangeClosedCurveSeam( double t )
|
|
{
|
|
//int saved_is_closed_helper = m_is_closed_helper;
|
|
|
|
if ( SegmentCount() == 1 )
|
|
{
|
|
// A ON_PolyEdgeSegment cannot have its start/end
|
|
// changed. Split it into two segments and let
|
|
// ON_PolyCurve::ChangeClosedCurveSeam() do the work.
|
|
if ( !IsClosed() )
|
|
return false;
|
|
|
|
ON_Interval crvd = Domain();
|
|
double s = crvd.NormalizedParameterAt(t);
|
|
|
|
if ( s <= ON_SQRT_EPSILON || s >= (1.0 - ON_SQRT_EPSILON) )
|
|
{
|
|
s = fmod(s,1.0);
|
|
if ( s < 0.0 )
|
|
s += 1.0;
|
|
if ( fabs(s) <= ON_SQRT_EPSILON || fabs(1.0-s) <= ON_SQRT_EPSILON )
|
|
{
|
|
// split parameter is at start/end of this segment
|
|
if ( t != crvd[0] )
|
|
{
|
|
DestroyRuntimeCache();
|
|
SetDomain(t,t+crvd.Length() );
|
|
//m_is_closed_helper = saved_is_closed_helper;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ON_PolyEdgeSegment* left_seg = SegmentCurve(0);
|
|
if ( 0 == left_seg )
|
|
return false;
|
|
|
|
DestroyRuntimeCache();
|
|
|
|
ON_Curve* left = left_seg;
|
|
ON_Curve* right = 0;
|
|
double segt = SegmentCurveParameter(t);
|
|
if ( !left_seg->Split(segt,left,right) )
|
|
return false;
|
|
SetDomain(crvd[0],t);
|
|
|
|
ON_PolyEdgeSegment* right_seg = ON_PolyEdgeSegment::Cast(right);
|
|
if ( 0 == right_seg )
|
|
return false;
|
|
Append(right_seg);
|
|
|
|
double st[3];
|
|
st[0] = crvd[0];
|
|
st[1] = t;
|
|
st[2] = crvd[1];
|
|
SetParameterization( st );
|
|
}
|
|
|
|
// ON_PolyCurve::ChangeClosedCurveSeam works fine on
|
|
// two or more segments.
|
|
bool rc = ON_PolyCurve::ChangeClosedCurveSeam(t);
|
|
//if ( saved_is_closed_helper )
|
|
// m_is_closed_helper = saved_is_closed_helper;
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::PrependAndMatch(ON_Curve*)
|
|
{
|
|
return false; // cannot change edges
|
|
}
|
|
|
|
|
|
bool ON_PolyEdgeCurve::AppendAndMatch(ON_Curve*)
|
|
{
|
|
return false; // cannot change edges
|
|
}
|
|
|
|
ON_Curve* ON_PolyEdgeSegment::DuplicateCurve() const
|
|
{
|
|
return ON_CurveProxy::DuplicateCurve();
|
|
|
|
// 21 December 2004 Dale Lear
|
|
// This is wrong. I did it some time ago as a quick
|
|
// fix for one of Lowell's early uses of CRhinoPolyEdges
|
|
// however, this will cause lots of crashes now that
|
|
// all commands have to deal with polyedges and the code
|
|
// in those commands assumes that DuplicateCurve() returns
|
|
// a valid stand-alone curve. If you end up here and
|
|
// wish this code still worked the old way, please get
|
|
// in touch with Dale Lear and we'll find a way to get
|
|
// your code to work.
|
|
// NO // ON_PolyEdgeSegment* dup = Duplicate();
|
|
// NO // return dup;
|
|
}
|
|
|
|
ON_Curve* ON_PolyEdgeCurve::DuplicateCurve() const
|
|
{
|
|
return ON_PolyCurve::DuplicateCurve();
|
|
|
|
// 21 December 2004 Dale Lear
|
|
// The code below is wrong. I wrote it some time ago as a quick
|
|
// fix for one of Lowell's early uses of CRhinoPolyEdges
|
|
// however, this will cause lots of crashes now that
|
|
// all commands have to deal with polyedges and the code
|
|
// in those commands assumes that DuplicateCurve() returns
|
|
// a valid stand-alone curve. If you end up here and
|
|
// wish this code still worked the old way, please get
|
|
// in touch with Dale Lear and we'll find a way to get
|
|
// your code to work.
|
|
|
|
// NO // int cnt = Count();
|
|
// NO // ON_SimpleArray<double> t(cnt+1);
|
|
// NO // ON_PolyEdgeCurve* dup_crv = new ON_PolyEdgeCurve();
|
|
// NO //
|
|
// NO // t.Append(Domain()[0]);
|
|
// NO //
|
|
// NO // for( int i=0; i<cnt; i++)
|
|
// NO // {
|
|
// NO // const ON_Curve* seg = SegmentCurve(i);
|
|
// NO // if ( seg )
|
|
// NO // {
|
|
// NO // t.Append(SegmentDomain(i)[1]);
|
|
// NO // dup_crv->ON_PolyCurve::Append( seg->DuplicateCurve() );
|
|
// NO // }
|
|
// NO // }
|
|
// NO //
|
|
// NO // if( cnt > 0 && cnt+1 == t.Count() )
|
|
// NO // {
|
|
// NO // dup_crv->SetParameterization( t.Array() );
|
|
// NO // }
|
|
// NO //
|
|
// NO // dup_crv->m_ev_srf_tan_mode = m_ev_srf_tan_mode;
|
|
// NO // dup_crv->m_is_closed_helper = m_is_closed_helper;
|
|
// NO //
|
|
// NO // return dup_crv;
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::IsClosed(void) const
|
|
{
|
|
bool rc = ON_CurveProxy::IsClosed();
|
|
if ( !rc
|
|
&& m_edge
|
|
&& m_edge->m_vi[0] == m_edge->m_vi[1]
|
|
&& m_edge->ProxyCurve() == ProxyCurve()
|
|
&& m_edge->ProxyCurveDomain() == ProxyCurveDomain()
|
|
&& 0 != ProxyCurve()
|
|
&& ProxyCurve()->Domain() == ProxyCurveDomain()
|
|
)
|
|
{
|
|
rc = m_edge->IsClosed();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
// 7-1-03 lw added override to unset cached closed flag
|
|
// when a segment is removed
|
|
bool ON_PolyEdgeCurve::Remove( int segment_index )
|
|
{
|
|
bool rc = ON_PolyCurve::Remove( segment_index);
|
|
//if( rc)
|
|
// m_is_closed_helper = 0; // Cached closed flag...
|
|
return rc;
|
|
}
|
|
bool ON_PolyEdgeCurve::Remove( )
|
|
{
|
|
return Remove(Count()-1);
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::IsClosed(void) const
|
|
{
|
|
bool rc = ON_PolyCurve::IsClosed();
|
|
|
|
if ( !rc && SegmentCount() > 1 )
|
|
{
|
|
// Since the segments that make up a ON_PolyEdgeCurve
|
|
// cannot have their ends matched (because the curves
|
|
// belong to objects already in the rhino model),
|
|
// the IsClosed() test has to tolerate larger gaps
|
|
// in brep topology.
|
|
//
|
|
// If the start and end segments are edges that belong
|
|
// to the same brep, then they "join" if and only if
|
|
// they share a vertex.
|
|
const ON_PolyEdgeSegment* seg0 = SegmentCurve(0);
|
|
const ON_PolyEdgeSegment* seg1 = SegmentCurve(SegmentCount()-1);
|
|
|
|
const ON_BrepEdge* edge0 = seg0->BrepEdge();
|
|
const ON_BrepEdge* edge1 = seg1->BrepEdge();
|
|
|
|
if ( edge0 && edge1 && edge0->Brep() == edge1->Brep() )
|
|
{
|
|
// check for topological closure
|
|
//
|
|
// Do NOT add a test for sloppy geometric closure here.
|
|
// If the edges are in the same brep and they don't
|
|
// meet topologically, then there is something in the
|
|
// brep that is separating the edges.
|
|
int evi0 = seg0->ReversedEdgeDir() ? 1 : 0;
|
|
int evi1 = seg1->ReversedEdgeDir() ? 0 : 1;
|
|
double et0 = seg0->EdgeParameter(seg0->Domain()[0]);
|
|
double et1 = seg1->EdgeParameter(seg1->Domain()[1]);
|
|
if ( et0 != ON_UNSET_VALUE && et1 != ON_UNSET_VALUE )
|
|
{
|
|
ON_Interval edom0 = edge0->Domain();
|
|
ON_Interval edom1 = edge1->Domain();
|
|
if ( et0 == edom0[evi0] && et1 == edom1[evi1] )
|
|
{
|
|
// The polyedge starts at the (evi0?end:start) of edge0
|
|
// and ends at the (ev1?end:start) of edge1.
|
|
if ( edge0->m_vi[evi0] == edge1->m_vi[evi1] )
|
|
{
|
|
// the polyedge start/ends at a common vertex
|
|
rc = true;
|
|
}
|
|
}
|
|
else if ( edge0 == edge1
|
|
&& fabs(et0-et1) <= ON_ZERO_TOLERANCE
|
|
&& edom0.Includes(et0,true)
|
|
&& edom1.Includes(et1,true)
|
|
)
|
|
{
|
|
// The start/end of the polyedge is an interior point
|
|
// of a single edge. (This happens when the "seam" gets
|
|
// adjusted to be inside of an edge.) It is unlikely that
|
|
// ON_PolyCurve::IsClosed() would return false in this
|
|
// case, but this check should keep everybody happy.
|
|
rc = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::Create( const ON_BrepTrim* trim, const ON_UUID& object_id )
|
|
{
|
|
bool rc = false;
|
|
Destroy();
|
|
//m_is_closed_helper = 0;
|
|
if ( trim )
|
|
{
|
|
ON_PolyEdgeSegment* segment = new ON_PolyEdgeSegment();
|
|
rc = segment->Create(trim,object_id);
|
|
if (rc )
|
|
Append(segment);
|
|
else
|
|
delete segment;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::Create( const ON_Curve* curve, const ON_UUID& object_id )
|
|
{
|
|
bool rc = false;
|
|
Destroy();
|
|
//m_is_closed_helper = 0;
|
|
if ( curve )
|
|
{
|
|
ON_PolyEdgeSegment* segment = new ON_PolyEdgeSegment();
|
|
rc = segment->Create(curve,object_id);
|
|
if (rc )
|
|
Append(segment);
|
|
else
|
|
delete segment;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int ON_PolyEdgeCurve::SegmentCount() const
|
|
{
|
|
return ON_PolyCurve::Count();
|
|
}
|
|
|
|
ON_PolyEdgeSegment* ON_PolyEdgeCurve::SegmentCurve(
|
|
int segment_index
|
|
) const
|
|
{
|
|
return ON_PolyEdgeSegment::Cast(ON_PolyCurve::SegmentCurve(segment_index));
|
|
}
|
|
|
|
|
|
ON_PolyEdgeSegment* ON_PolyEdgeCurve::operator[](int segment_index) const
|
|
{
|
|
return SegmentCurve(segment_index);
|
|
}
|
|
|
|
void ON_PolyEdgeCurve::DestroyRuntimeCache( bool bDelete )
|
|
{
|
|
//m_is_closed_helper = 0;
|
|
ON_PolyCurve::DestroyRuntimeCache(bDelete);
|
|
}
|
|
|
|
void ON_PolyEdgeSegment::DestroyRuntimeCache( bool bDelete )
|
|
{
|
|
ClearEvalCacheHelper();
|
|
ON_CurveProxy::DestroyRuntimeCache(bDelete);
|
|
}
|
|
|
|
|
|
bool ON_PolyEdgeCurve::Prepend( ON_PolyEdgeSegment* new_segment )
|
|
{
|
|
DestroyRuntimeCache();
|
|
bool rc = false;
|
|
if ( new_segment )
|
|
{
|
|
if ( Count() > 0 )
|
|
{
|
|
// keep segment domains in synch with polycurve domain
|
|
// so that parameter bookkeeping is easy.
|
|
ON_Interval cdom = Domain();
|
|
ON_Interval sdom = new_segment->Domain();
|
|
if ( sdom[1] != cdom[0] )
|
|
{
|
|
sdom[0] = cdom[0] - sdom.Length();
|
|
sdom[1] = cdom[0];
|
|
new_segment->SetDomain(sdom[0],sdom[1]);
|
|
}
|
|
}
|
|
rc = ON_PolyCurve::Prepend(new_segment);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::Append( ON_PolyEdgeSegment* new_segment )
|
|
{
|
|
DestroyRuntimeCache();
|
|
bool rc = false;
|
|
if ( new_segment )
|
|
{
|
|
//m_is_closed_helper = 0;
|
|
if ( Count() > 0 )
|
|
{
|
|
// keep segment domains in synch with polycurve domain
|
|
// so that parameter bookkeeping is easy.
|
|
ON_Interval cdom = Domain();
|
|
ON_Interval sdom = new_segment->Domain();
|
|
if ( sdom[0] != cdom[1] )
|
|
{
|
|
sdom[1] = cdom[1] + sdom.Length();
|
|
sdom[0] = cdom[1];
|
|
new_segment->SetDomain(sdom[0],sdom[1]);
|
|
}
|
|
}
|
|
rc = ON_PolyCurve::Append(new_segment);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeCurve::Insert(
|
|
int segment_index,
|
|
ON_PolyEdgeSegment* new_segment
|
|
)
|
|
{
|
|
DestroyRuntimeCache();
|
|
bool rc = false;
|
|
if ( segment_index > 0 )
|
|
{
|
|
//m_is_closed_helper = 0;
|
|
rc = ON_PolyCurve::Insert(segment_index,new_segment);
|
|
if ( rc )
|
|
{
|
|
int i;
|
|
for ( i = segment_index; i < Count(); i++ )
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve(i);
|
|
ON_Interval d = SegmentDomain(i);
|
|
seg->SetDomain(d[0],d[1]);
|
|
}
|
|
}
|
|
}
|
|
else if ( segment_index == 0 )
|
|
rc = Prepend(new_segment);
|
|
return rc;
|
|
}
|
|
|
|
const ON_BrepEdge* ON_PolyEdgeCurve::EdgeAt(double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->BrepEdge() : 0;
|
|
}
|
|
|
|
const ON_BrepTrim* ON_PolyEdgeCurve::TrimAt(double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->BrepTrim() : 0;
|
|
}
|
|
|
|
const ON_Brep* ON_PolyEdgeCurve::BrepAt(double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->Brep() : 0;
|
|
}
|
|
|
|
const ON_BrepFace* ON_PolyEdgeCurve::FaceAt(double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->BrepFace() : 0;
|
|
}
|
|
|
|
const ON_Surface* ON_PolyEdgeCurve::SurfaceAt(double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->Surface() : 0;
|
|
}
|
|
|
|
ON_Surface::ISO ON_PolyEdgeCurve::IsoType( double t) const
|
|
{
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( SegmentIndex(t) );
|
|
return seg ? seg->IsoType() : ON_Surface::not_iso;
|
|
}
|
|
|
|
|
|
double ON_PolyEdgeCurve::EdgeParameter(double t) const
|
|
{
|
|
double edge_t = ON_UNSET_VALUE;
|
|
int segment_index = SegmentIndex(t);
|
|
ON_PolyEdgeSegment* seg = SegmentCurve( segment_index );
|
|
if ( seg )
|
|
{
|
|
ON_Interval pdom = SegmentDomain(segment_index);
|
|
ON_Interval sdom = seg->Domain();
|
|
if ( sdom != pdom )
|
|
{
|
|
double s = pdom.NormalizedParameterAt(t);
|
|
t = sdom.ParameterAt(s);
|
|
}
|
|
edge_t = seg->EdgeParameter(t);
|
|
}
|
|
return edge_t;
|
|
}
|
|
|
|
|
|
// Test if there are any surface edges in the polyedge
|
|
bool ON_PolyEdgeCurve::ContainsAnyEdges() const
|
|
{
|
|
int i, count = SegmentCount();
|
|
for( i = 0; i < count; i++)
|
|
{
|
|
ON_PolyEdgeSegment* segment = SegmentCurve(i);
|
|
if( 0 != segment && nullptr != segment->BrepEdge())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Test if all segments of the polyedge are surface edges
|
|
bool ON_PolyEdgeCurve::ContainsAllEdges() const
|
|
{
|
|
int i, count = SegmentCount();
|
|
for( i = 0; i < count; i++)
|
|
{
|
|
ON_PolyEdgeSegment* segment = SegmentCurve(i);
|
|
if( nullptr == segment || nullptr == segment->BrepEdge())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int ON_PolyEdgeCurve::FindEdge( const ON_BrepEdge* edge) const
|
|
{
|
|
int rc = -1;
|
|
if ( 0 != edge )
|
|
{
|
|
int i, count = SegmentCount();
|
|
for( i = 0; i < count; i++)
|
|
{
|
|
ON_PolyEdgeSegment* segment = SegmentCurve(i);
|
|
if ( 0 != segment && edge == segment->BrepEdge() )
|
|
{
|
|
rc = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int ON_PolyEdgeCurve::FindTrim( const ON_BrepTrim* trim) const
|
|
{
|
|
int rc = -1;
|
|
if ( 0 != trim )
|
|
{
|
|
int i, count = SegmentCount();
|
|
for( i = 0; i < count; i++)
|
|
{
|
|
ON_PolyEdgeSegment* segment = SegmentCurve(i);
|
|
if ( 0 != segment && trim == segment->BrepTrim() )
|
|
{
|
|
rc = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int ON_PolyEdgeCurve::FindCurve( const ON_Curve* curve) const
|
|
{
|
|
int rc = -1;
|
|
if ( 0 != curve )
|
|
{
|
|
int i, count = SegmentCount();
|
|
for( i = 0; i < count; i++)
|
|
{
|
|
ON_PolyEdgeSegment* segment = SegmentCurve(i);
|
|
if ( 0 != segment
|
|
&& (curve == segment || curve == segment->ProxyCurve() || curve == segment->BrepEdge()) )
|
|
{
|
|
rc = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::Write( ON_BinaryArchive& archive ) const
|
|
{
|
|
bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
|
|
if (!rc)
|
|
return false;
|
|
for(;;)
|
|
{
|
|
rc = archive.WriteUuid(m_object_id);
|
|
if (!rc) break;
|
|
rc = archive.WriteComponentIndex(m_component_index);
|
|
if (!rc) break;
|
|
rc = archive.WriteInterval(m_edge_domain);
|
|
if (!rc) break;
|
|
rc = archive.WriteInterval(m_trim_domain);
|
|
if (!rc) break;
|
|
bool b = ON_CurveProxy::ProxyCurveIsReversed();
|
|
rc = archive.WriteBool(b);
|
|
if (!rc) break;
|
|
rc = archive.WriteInterval(ON_CurveProxy::Domain());
|
|
if (!rc) break;
|
|
rc = archive.WriteInterval(ON_CurveProxy::ProxyCurveDomain());
|
|
if (!rc) break;
|
|
|
|
break;
|
|
}
|
|
if ( !archive.EndWrite3dmChunk() )
|
|
rc = false;
|
|
return rc;
|
|
}
|
|
|
|
bool ON_PolyEdgeSegment::Read( ON_BinaryArchive& archive )
|
|
{
|
|
Init();
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
|
|
if (!rc)
|
|
return false;
|
|
for(;;)
|
|
{
|
|
rc = (1 == major_version);
|
|
if ( !rc )
|
|
break;
|
|
|
|
rc = archive.ReadUuid(m_object_id);
|
|
if (!rc) break;
|
|
rc = archive.ReadComponentIndex(m_component_index);
|
|
if (!rc) break;
|
|
rc = archive.ReadInterval(m_edge_domain);
|
|
if (!rc) break;
|
|
rc = archive.ReadInterval(m_trim_domain);
|
|
if (!rc) break;
|
|
|
|
// Read ON_ProxyCurve values we need
|
|
bool bReversed = false;
|
|
rc = archive.ReadBool(&bReversed);
|
|
if (!rc) break;
|
|
ON_Interval this_domain;
|
|
rc = archive.ReadInterval(this_domain);
|
|
if (!rc) break;
|
|
ON_Interval real_curve_domain;
|
|
rc = archive.ReadInterval(real_curve_domain);
|
|
if (!rc) break;
|
|
|
|
if ( bReversed)
|
|
ON_CurveProxy::Reverse();
|
|
ON_CurveProxy::SetDomain(this_domain);
|
|
ON_CurveProxy::SetProxyCurveDomain(real_curve_domain);
|
|
|
|
break;
|
|
}
|
|
if ( !archive.EndRead3dmChunk() )
|
|
rc = false;
|
|
return rc;
|
|
}
|
|
|