Ejemplo n.º 1
0
RH_C_FUNCTION void ON_Brep_DuplicateEdgeCurves(const ON_Brep* pBrep, ON_SimpleArray<ON_Curve*>* pOutCurves, bool nakedOnly)
{
  if (pBrep && pOutCurves)
  {
    for(int i = 0; i < pBrep->m_E.Count(); i++)
    {
      const ON_BrepEdge& edge = pBrep->m_E[i];
      if( nakedOnly && edge.m_ti.Count()!=1 )
        continue;

      ON_Curve* curve = edge.DuplicateCurve();
      if(curve)
      {
        // From RhinoScript:
        // make the curve direction go in the natural boundary loop direction
        // so that the curve directions come out consistantly
        if( pBrep->m_T[edge.m_ti[0]].m_bRev3d )
          curve->Reverse();
        if( pBrep->m_T[edge.m_ti[0]].Face()->m_bRev )
          curve->Reverse();

        pOutCurves->Append(curve);
      }
    }
  }
}
Ejemplo n.º 2
0
ON_Curve* ON_SurfaceProxy::Pushup( const ON_Curve& curve_2d,
                  double tolerance,
                  const ON_Interval* curve_2d_subdomain
                  ) const
{
  ON_Curve* pushupcurve = 0;
  if ( 0 != m_surface )
  {
    if ( m_bTransposed )
    {
      ON_Curve* transposedcurve = curve_2d.DuplicateCurve();
      if ( 0 != transposedcurve )
      {
        transposedcurve->SwapCoordinates(0,1);
        pushupcurve = m_surface->Pushup( *transposedcurve, tolerance, curve_2d_subdomain );
        delete transposedcurve;
        transposedcurve = 0;
      }
    }
    else
    {
      pushupcurve = m_surface->Pushup( curve_2d, tolerance, curve_2d_subdomain );
    }
  }
  return pushupcurve;
}
BOOL COrientOnCrvXform::CalculateTransform( CRhinoViewport& vp, const ON_3dPoint& pt, ON_Xform& xform )
{
  BOOL bResult = FALSE;

  if( m_path_curve )
  {
    double t = 0.0;
    if( m_path_curve->GetClosestPoint(pt, &t) )
    {
      ON_3dPoint origin = m_path_curve->PointAt( t );
      ON_Plane dest_plane;
      if( m_perp_mode )
      {
        ON_3dVector tangent = m_path_curve->TangentAt( t );
        MakeNormalPlane( origin, tangent, dest_plane );
      }
      else
      {
        dest_plane.origin = origin;
        dest_plane.xaxis = m_path_curve->TangentAt( t );
        dest_plane.zaxis = m_base_plane.zaxis;
        dest_plane.yaxis = ON_CrossProduct( dest_plane.zaxis, dest_plane.xaxis );
        dest_plane.UpdateEquation();
      }
      xform.Rotation( m_base_plane, dest_plane );
      bResult = xform.IsValid() ? TRUE : FALSE;
    }
  }

  return bResult;
}
Ejemplo n.º 4
0
static void UnrotateHatch(ON_Hatch* hatch)
{
  double a = arbaxisRotation(hatch->Plane());
  ON_Plane& plane = *(ON_Plane*)(&hatch->Plane());
  if(fabs(a) > ON_ZERO_TOLERANCE)
  {
    plane.Rotate(-a, plane.zaxis);
    for(int i = 0; i < hatch->LoopCount(); i++)
    {
      ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve();
      pC->Rotate(a, ON_zaxis, ON_origin);
    }
    hatch->SetPatternRotation(hatch->PatternRotation()+a);
  }
  ON_3dPoint P;
  plane.ClosestPointTo(ON_origin, &P.x, &P.y);

  if(fabs(P.x) > ON_ZERO_TOLERANCE ||fabs(P.y) > ON_ZERO_TOLERANCE ||fabs(P.z) > ON_ZERO_TOLERANCE)
  {
    ON_2dVector V(-P.x, -P.y);
    for(int i = 0; i < hatch->LoopCount(); i++)
    {
      ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve();
      pC->Translate(V);
    }
    P = plane.PointAt(P.x, P.y);
    plane.origin = P;
  }
}
Ejemplo n.º 5
0
static
bool ON_BrepExtrudeHelper_CheckPathCurve( const ON_Curve& path_curve, ON_3dVector& path_vector )
{
  ON_Line path_line;
  path_line.from = path_curve.PointAtStart();
  path_line.to = path_curve.PointAtEnd();
  path_vector = path_line.Direction();
  return ( path_vector.IsZero() ? false : true );
}
Ejemplo n.º 6
0
RH_C_FUNCTION ON_MassProperties* ON_Hatch_AreaMassProperties(const ON_Hatch* pConstHatch, double rel_tol, double abs_tol)
{
  ON_MassProperties* rc = NULL;
  if( pConstHatch )
  {
    ON_BoundingBox bbox = pConstHatch->BoundingBox();
    ON_3dPoint basepoint = bbox.Center();
    basepoint = pConstHatch->Plane().ClosestPointTo(basepoint);

    ON_ClassArray<ON_MassProperties> list;

    for( int i=0; i<pConstHatch->LoopCount(); i++ )
    {
      const ON_HatchLoop* pLoop = pConstHatch->Loop(i);
      if( NULL==pLoop )
        continue;
      ON_Curve* pCurve = pConstHatch->LoopCurve3d(i);
      if( NULL==pCurve )
        continue;
      
      ON_MassProperties mp;
      if( pCurve->AreaMassProperties(basepoint, pConstHatch->Plane().Normal(), mp, true, true, true, true, rel_tol, abs_tol) )
      {
        mp.m_mass = fabs(mp.m_mass);
        if( pLoop->Type() == ON_HatchLoop::ltInner )
          mp.m_mass = -mp.m_mass;

        list.Append(mp);
      }
      delete pCurve;
    }

    if( list.Count()==1 )
    {
      rc = new ON_MassProperties();
      *rc = list[0];
    }
    else if( list.Count()>1 )
    {
      int count = list.Count();
      const ON_MassProperties* pieces = list.Array();
      rc = new ON_MassProperties();
      if( !rc->Sum(count, pieces) )
      {
        delete rc;
        rc = NULL;
      }
    }
  }
  return rc;
}
Ejemplo n.º 7
0
bool ON_HatchLoop::SetCurve( const ON_Curve& curve)
{
  ON_Curve* pC = curve.DuplicateCurve();
  if( pC)
  {
    if(pC->Dimension() == 3 && !pC->ChangeDimension(2))
      return false;

    if( m_p2dCurve)
      delete m_p2dCurve;
    m_p2dCurve = pC;
  }
  return true;
}
ON_Surface::ISO
ON_SurfaceProxy::IsIsoparametric( // returns isoparametric status of 2d curve
    const ON_Curve& crv,
    const ON_Interval* subdomain
) const
{
    // this is a virtual overide of an ON_Surface::IsIsoparametric

    const ON_Curve* pC = &crv;
    ON_Curve* pTranC = NULL;
    if(m_bTransposed)
    {
        pTranC = crv.DuplicateCurve();
        pTranC->SwapCoordinates(0,1);
        pC = pTranC;
    }

    ON_Surface::ISO iso = m_surface->IsIsoparametric( *pC, subdomain);

    if (pTranC)
    {
        switch(iso)
        {
        case x_iso:
            iso = y_iso;
            break;
        case y_iso:
            iso = x_iso;
            break;
        case W_iso:
            iso = S_iso;
            break;
        case S_iso:
            iso = W_iso;
            break;
        case N_iso:
            iso = E_iso;
            break;
        case E_iso:
            iso = N_iso;
            break;
        default:
            // intentionally ignoring other ON_Surface::ISO enum values
            break;
        }
        delete pTranC;
    }

    return iso;
}
Ejemplo n.º 9
0
BOOL ON_Hatch::GetBBox( double* bmin, double* bmax, BOOL bGrowBox) const
{
  int i;
  int count = m_loops.Count();
  BOOL rc = true;
  ON_Curve* pC;
  for( i = 0; rc && i < count; i++)
  {
    pC = LoopCurve3d( i);
    if( pC)
    {
      rc = pC->GetBBox( bmin, bmax, i?true:bGrowBox);
      delete pC;
    }
  }
  return rc;
}
Ejemplo n.º 10
0
void ON_CurveProxy::DestroyRuntimeCache( bool bDelete )
{
  if ( m_ctree ) 
  {
#if defined(OPENNURBS_PLUS_INC_)
    if ( bDelete )
      delete m_ctree;
#endif
    m_ctree = 0;
  }
  if ( 0 != m_real_curve && m_real_curve != this )
  {
    ON_Curve* curve = const_cast<ON_Curve*>(m_real_curve);
    if ( 0 != curve )
      curve->DestroyRuntimeCache( bDelete );
  }
}
Ejemplo n.º 11
0
ON_Curve* ON_SurfaceProxy::Pullback( const ON_Curve& curve_3d,
                  double tolerance,
                  const ON_Interval* curve_3d_subdomain,
                  ON_3dPoint start_uv,
                  ON_3dPoint end_uv
                  ) const
{
  ON_Curve* pullbackcurve = 0;
  if ( 0 != m_surface )
  {
    pullbackcurve = m_surface->Pullback( curve_3d, tolerance, curve_3d_subdomain, start_uv, end_uv );
    if ( m_bTransposed && 0 != pullbackcurve )
    {
      pullbackcurve->SwapCoordinates(0,1);
    }
  }
  return pullbackcurve;
}
Ejemplo n.º 12
0
bool ON_HatchLoop::SetCurve( const ON_Curve& curve)
{
  ON_Curve* pC = curve.DuplicateCurve();
  if( pC)
  {
    if( m_p2dCurve)
      delete m_p2dCurve;
    m_p2dCurve = pC;
  }
  return true;
}
Ejemplo n.º 13
0
// Copy the 2d curve, make it 3d, and transform it
// to the 3d plane position
ON_Curve* ON_Hatch::LoopCurve3d( int index) const
{
  int count = m_loops.Count();
  ON_Curve* pC = NULL;

  if( index >= 0 && index < count)
  {
    if( m_loops[index]->Curve())
    {
      pC = m_loops[index]->Curve()->DuplicateCurve();
      if( pC)
      {
        pC->ChangeDimension( 3);

        ON_Xform xf;
        xf.Rotation( ON_xy_plane, m_plane);

        pC->Transform( xf);
      }
    }
  }
  return pC;
}
Ejemplo n.º 14
0
RH_C_FUNCTION ON_Curve* ON_Curve_TrimExtend( const ON_Curve* pCurve, double t0, double t1, bool trimming)
{
  ON_Curve* rc = NULL;
  if( pCurve )
  {
    if( trimming )
    {
      rc = ::ON_TrimCurve(*pCurve, ON_Interval(t0,t1));
    }
    else
    {
      ON_Curve* pNewCurve = pCurve->DuplicateCurve();
      if( pNewCurve )
      {
        if( pNewCurve->Extend(ON_Interval(t0,t1)) )
          rc = pNewCurve;
        else
          delete pNewCurve;
      }
    }
  }
  return rc;
}
Ejemplo n.º 15
0
RH_C_FUNCTION void ON_Brep_DuplicateEdgeCurves(const ON_Brep* pConstBrep, ON_SimpleArray<ON_Curve*>* pOutCurves, bool nakedOnly, bool nakedOuter, bool nakedInner)
{
  if (pConstBrep && pOutCurves)
  {
    for(int i = 0; i < pConstBrep->m_E.Count(); i++)
    {
      const ON_BrepEdge& edge = pConstBrep->m_E[i];
      if( nakedOnly )
      {
        if( edge.m_ti.Count() != 1 )
          continue;

        const ON_BrepTrim& trim = pConstBrep->m_T[edge.m_ti[0]];
        const ON_BrepLoop& loop = pConstBrep->m_L[trim.m_li];

        bool acceptable = (nakedOuter && loop.m_type == ON_BrepLoop::outer) ||
                          (nakedInner && loop.m_type == ON_BrepLoop::inner);
        if( !acceptable )
          continue;
      }

      ON_Curve* curve = edge.DuplicateCurve();
      if(curve)
      {
        // From RhinoScript:
        // make the curve direction go in the natural boundary loop direction
        // so that the curve directions come out consistantly
        if( pConstBrep->m_T[edge.m_ti[0]].m_bRev3d )
          curve->Reverse();
        if( pConstBrep->m_T[edge.m_ti[0]].Face()->m_bRev )
          curve->Reverse();

        pOutCurves->Append(curve);
      }
    }
  }
}
Ejemplo n.º 16
0
// Add a curve to the partial boundingbox result.
static void ON_Brep_GetTightCurveBoundingBox_Helper( const ON_Curve& crv, ON_BoundingBox& bbox, const ON_Xform* xform, const ON_Xform* xform_inverse )
{
  // Get loose boundingbox of curve.
  ON_BoundingBox tempbox;
  if( !crv.GetBoundingBox(tempbox, false) )
    return;

  // Transform the loose box if necessary. 
  // Note: transforming a box might result in a larger box, 
  //       it's better to transform the curve, 
  //       which might actually result in a smaller box.
  if( xform_inverse )
  {
    tempbox.Transform(*xform_inverse); 
  }

  // If loose boundingbox of curve is inside partial result, return.
  if( bbox.Includes(tempbox, false) )
    return;

  // Get tight boundingbox of curve, grow partial result.
  if( crv.GetTightBoundingBox(tempbox, false, xform) )
    bbox.Union(tempbox);
}
Ejemplo n.º 17
0
static void
test_pci(ON_3dPoint &p, ON_Curve &c)
{
    ON_wString wstr;
    ON_TextLog textlog(wstr);
    ON_ClassArray<ON_PX_EVENT> x;

    // Use default tolerance
    ON_Intersect(p, c, x);

    ON_3dPoint start = c.PointAtStart();
    ON_3dPoint end = c.PointAtEnd();
    bu_log("(%f,%f,%f) and [(%f,%f,%f) to (%f,%f,%f)]:\n",
	   p[0], p[1], p[2], start[0], start[1], start[2], end[0], end[1], end[2]);
    if (x.Count() == 0) {
	bu_log("No intersection.\n");
    } else {
	for (int i = 0; i < x.Count(); i++)
	    x[i].Dump(textlog);
	ON_String str(wstr);
	bu_log(str.Array());
    }
    bu_log("\n\n");
}
Ejemplo n.º 18
0
void ON_GL( const ON_Curve& curve,
              GLUnurbsObj* nobj, // created with gluNewNurbsRenderer )
              GLenum type, // = 0 (and type is automatically set)
              double xform[][4]
            )
{
  const ON_PolyCurve* poly_curve = ON_PolyCurve::Cast(&curve);
  if ( poly_curve ) 
  {
    ON_Curve* pSegmentCurve = 0;
    int segment_count = poly_curve->Count();
    int i;
    for ( i = 0; i < segment_count; i++ ) {
      pSegmentCurve = poly_curve->SegmentCurve(i);
      if ( pSegmentCurve )
        ON_GL( *pSegmentCurve, nobj, type, xform );
    }
    return;
  }

  const ON_CurveProxy* curve_proxy = ON_CurveProxy::Cast(&curve);
  if ( curve_proxy && !curve_proxy->ProxyCurveIsReversed() ) 
  {
    const ON_Curve* real_curve = curve_proxy->ProxyCurve();
    if ( 0 == real_curve )
      return;
    if ( curve_proxy == real_curve )
      return;
    if ( curve_proxy->ProxyCurveDomain() == real_curve->Domain() )
    {
      ON_GL( *real_curve, nobj, type, xform );
      return;
    }
  }

  {
    ON_NurbsCurve tmp;
    const ON_NurbsCurve* nurbs_curve = ON_NurbsCurve::Cast(&curve);
    if ( !nurbs_curve ) 
    {
      if ( curve.GetNurbForm(tmp) )
        nurbs_curve = &tmp;
    }
    ON_GL( *nurbs_curve, nobj, type, true, NULL, xform );
  }
}
Ejemplo n.º 19
0
int ON_BrepExtrudeVertex( 
          ON_Brep& brep,
          int vertex_index,
          const ON_Curve& path_curve
          )
{
  ON_3dVector path_vector;
  if ( vertex_index < 0 && vertex_index >= brep.m_V.Count() )
    return false;
  if ( !ON_BrepExtrudeHelper_CheckPathCurve(path_curve,path_vector) )
    return false;
  ON_Curve* c3 = path_curve.Duplicate();
  brep.m_V.Reserve( brep.m_V.Count() + 1 );
  ON_BrepVertex& v0 = brep.m_V[vertex_index];
  ON_BrepVertex& v1 = brep.NewVertex( v0.point + path_vector, 0.0 );
  c3->Translate( v0.point - c3->PointAtStart() );
  int c3i = brep.AddEdgeCurve( c3 );
  ON_BrepEdge& edge = brep.NewEdge( v0, v1, c3i );
  edge.m_tolerance = 0.0;
  return true;
}
Ejemplo n.º 20
0
ON_Surface::ISO
ON_Surface::IsIsoparametric( const ON_Curve& curve, const ON_Interval* subdomain ) const
{
  ISO iso = not_iso;

  if ( subdomain )
  {
    ON_Interval cdom = curve.Domain();
    double t0 = cdom.NormalizedParameterAt(subdomain->Min());
    double t1 = cdom.NormalizedParameterAt(subdomain->Max());
    if ( t0 < t1-ON_SQRT_EPSILON )
    {
      if ( (t0 > ON_SQRT_EPSILON && t0 < 1.0-ON_SQRT_EPSILON) || (t1 > ON_SQRT_EPSILON && t1 < 1.0-ON_SQRT_EPSILON) )
      {
        cdom.Intersection(*subdomain);
        if ( cdom.IsIncreasing() )
        {
          ON_NurbsCurve nurbs_curve;
          if ( curve.GetNurbForm( nurbs_curve, 0.0,&cdom) )
          {
            return IsIsoparametric( nurbs_curve, 0 );
          }
        }
      }
    }
  }


  ON_BoundingBox bbox;
  double tolerance = 0.0;
  const int dim = curve.Dimension();
  if ( (dim == 2 || dim==3) && curve.GetBoundingBox(bbox) ) 
  {
    iso = IsIsoparametric( bbox );
    switch (iso) {
    case x_iso:
    case W_iso:
    case E_iso:
      // make sure curve is a (nearly) vertical line
      // and weed out vertical scribbles
      tolerance = bbox.m_max.x - bbox.m_min.x;
      if ( tolerance < ON_ZERO_TOLERANCE && ON_ZERO_TOLERANCE*1024.0 <= (bbox.m_max.y-bbox.m_min.y) )
      {
        // 26 March 2007 Dale Lear
        //    If tolerance is tiny, then use ON_ZERO_TOLERANCE
        //    This fixes cases where iso curves where not getting
        //    the correct flag because tol=1e-16 and the closest
        //    point to line had calculation errors of 1e-15.
        tolerance = ON_ZERO_TOLERANCE;
      }
      if ( !curve.IsLinear( tolerance ) )
        iso = not_iso;
      break;
    case y_iso:
    case S_iso:
    case N_iso:
      // make sure curve is a (nearly) horizontal line
      // and weed out horizontal scribbles
      tolerance = bbox.m_max.y - bbox.m_min.y;
      if ( tolerance < ON_ZERO_TOLERANCE && ON_ZERO_TOLERANCE*1024.0 <= (bbox.m_max.x-bbox.m_min.x) )
      {
        // 26 March 2007 Dale Lear
        //    If tolerance is tiny, then use ON_ZERO_TOLERANCE
        //    This fixes cases where iso curves where not getting
        //    the correct flag because tol=1e-16 and the closest
        //    point to line had calculation errors of 1e-15.
        tolerance = ON_ZERO_TOLERANCE;
      }
      if ( !curve.IsLinear( tolerance ) )
        iso = not_iso;
      break;
    default:
      // nothing here
      break;
    }
  }
  return iso;
}
Ejemplo n.º 21
0
bool ON_BrepExtrude( 
          ON_Brep& brep,
          const ON_Curve& path_curve,
          bool bCap
          )
{
  ON_Workspace ws;
  const int vcount0 = brep.m_V.Count();
  const int tcount0 = brep.m_T.Count();
  const int lcount0 = brep.m_L.Count();
  const int ecount0 = brep.m_E.Count();
  const int fcount0 = brep.m_F.Count();

  const ON_3dPoint PathStart = path_curve.PointAtStart();
  ON_3dPoint P = path_curve.PointAtEnd();
  if ( !PathStart.IsValid() || !P.IsValid() )
    return false;
  const ON_3dVector height = P - PathStart;
  if ( !height.IsValid() || height.Length() <= ON_ZERO_TOLERANCE )
    return false;

  ON_Xform tr;
  tr.Translation(height);

  // count number of new sides
  int side_count = 0;
  int i, vi, ei, fi;
  bool* bSideEdge = (bool*)ws.GetIntMemory(ecount0*sizeof(bSideEdge[0]));
  for ( ei = 0; ei < ecount0; ei++ )
  {
    const ON_BrepEdge& e = brep.m_E[ei];
    if ( 1 == e.m_ti.Count() )
    {
      side_count++;
      bSideEdge[ei] = true;
    }
    else
    {
      bSideEdge[ei] = false;
    }
  }

  brep.m_V.Reserve( 2*vcount0 );
  i = 4*side_count + (bCap?tcount0:0);
  brep.m_T.Reserve( tcount0 + i );
  brep.m_C2.Reserve( brep.m_C2.Count() + i );
  brep.m_L.Reserve( lcount0 + side_count + (bCap?lcount0:0) );
  i = side_count + (bCap?ecount0:side_count);
  brep.m_E.Reserve( ecount0 + i );
  brep.m_C3.Reserve( brep.m_C3.Count() + i );
  i = side_count + (bCap?fcount0:0);
  brep.m_F.Reserve( fcount0 + i );
  brep.m_S.Reserve( brep.m_S.Count() + i );

  bool bOK = true;

  // build top vertices
  int* topvimap = ws.GetIntMemory(vcount0);
  memset(topvimap,0,vcount0*sizeof(topvimap[0]));
  if ( bCap )
  {
    for ( vi = 0; vi < vcount0; vi++ )
    {
      const ON_BrepVertex& bottomv = brep.m_V[vi];
      ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
      topvimap[vi] = topv.m_vertex_index;
    }
  }
  else
  {
    for ( ei = 0; ei < ecount0; ei++ )
    {
      if ( bSideEdge[ei] )
      {
        const ON_BrepEdge& bottome = brep.m_E[ei];
        int bottomvi0 = bottome.m_vi[0];
        if ( bottomvi0 < 0 || bottomvi0 >= vcount0 )
        {
          bOK = false;
          break;
        }
        int bottomvi1 = bottome.m_vi[1];
        if ( bottomvi1 < 0 || bottomvi1 >= vcount0 )
        {
          bOK = false;
          break;
        }
        if ( !topvimap[bottomvi0] )
        {
          const ON_BrepVertex& bottomv = brep.m_V[bottomvi0];
          ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
          topvimap[bottomvi0] = topv.m_vertex_index;
        }
        if ( !topvimap[bottomvi1] )
        {
          const ON_BrepVertex& bottomv = brep.m_V[bottomvi1];
          ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance);
          topvimap[bottomvi1] = topv.m_vertex_index;
        }
      }
    }
  }

  // build top edges
  int* topeimap = ws.GetIntMemory(ecount0);
  memset(topeimap,0,ecount0*sizeof(topeimap[0]));
  if ( bOK ) for ( ei = 0; ei < ecount0; ei++ )
  {
    if ( bCap || bSideEdge[ei] )
    {
      const ON_BrepEdge& bottome = brep.m_E[ei];
      ON_BrepVertex& topv0 = brep.m_V[topvimap[bottome.m_vi[0]]];
      ON_BrepVertex& topv1 = brep.m_V[topvimap[bottome.m_vi[1]]];
      ON_Curve* c3 = bottome.DuplicateCurve();
      if ( !c3 )
      {
        bOK = false;
        break;
      }
      c3->Transform(tr);
      int c3i = brep.AddEdgeCurve(c3);
      ON_BrepEdge& tope = brep.NewEdge(topv0,topv1,c3i,0,bottome.m_tolerance);
      topeimap[ei] = tope.m_edge_index;
    }
  }

  // build side edges
  int* sideveimap = ws.GetIntMemory(vcount0);
  memset(sideveimap,0,vcount0*sizeof(sideveimap[0]));
  if ( bOK ) for ( vi = 0; vi < vcount0; vi++ )
  {
    ON_BrepVertex& bottomv = brep.m_V[vi];
    for ( int vei = 0; vei < bottomv.m_ei.Count(); vei++ )
    {
      if ( bSideEdge[bottomv.m_ei[vei]] && topvimap[vi] )
      {
        ON_BrepVertex& topv = brep.m_V[topvimap[vi]];
        ON_Curve* c3 = path_curve.DuplicateCurve();
        if ( !c3 )
        {
          bOK = false;
        }
        else
        {
          ON_3dVector D = bottomv.point - PathStart;
          c3->Translate(D);
          int c3i = brep.AddEdgeCurve(c3);
          const ON_BrepEdge& e = brep.NewEdge(bottomv,topv,c3i,0,0.0);
          sideveimap[vi] = e.m_edge_index;
        }
        break;
      }
    }
  }

  if ( bOK && bCap )
  {
    // build top faces
    for (fi = 0; fi < fcount0; fi++ )
    {
      const ON_BrepFace& bottomf = brep.m_F[fi];
      ON_Surface* srf = bottomf.DuplicateSurface();
      if ( !srf )
      {
        bOK = false;
        break;
      }
      srf->Transform(tr);
      int si = brep.AddSurface(srf);
      ON_BrepFace& topf = brep.NewFace(si);
      topf.m_bRev = !bottomf.m_bRev;
      const int loop_count = bottomf.m_li.Count();
      topf.m_li.Reserve(loop_count);
      for ( int fli = 0; fli < loop_count; fli++ )
      {
        const ON_BrepLoop& bottoml = brep.m_L[bottomf.m_li[fli]];
        ON_BrepLoop& topl = brep.NewLoop(bottoml.m_type,topf);
        const int loop_trim_count = bottoml.m_ti.Count();
        topl.m_ti.Reserve(loop_trim_count);
        for ( int lti = 0; lti < loop_trim_count; lti++ )
        {
          const ON_BrepTrim& bottomt = brep.m_T[bottoml.m_ti[lti]];
          ON_NurbsCurve* c2 = ON_NurbsCurve::New();
          if ( !bottomt.GetNurbForm(*c2) )
          {
            delete c2;
            bOK = false;
            break;
          }
          int c2i = brep.AddTrimCurve(c2);
          ON_BrepTrim* topt = 0;
          if ( bottomt.m_ei >= 0 )
          {
            ON_BrepEdge& tope = brep.m_E[topeimap[bottomt.m_ei]];
            topt = &brep.NewTrim(tope,bottomt.m_bRev3d,topl,c2i);
          }
          else
          {
            // singular trim
            ON_BrepVertex& topv = brep.m_V[topvimap[bottomt.m_vi[0]]];
            topt = &brep.NewSingularTrim(topv,topl,bottomt.m_iso,c2i);
          }
          topt->m_tolerance[0] = bottomt.m_tolerance[0];
          topt->m_tolerance[1] = bottomt.m_tolerance[1];
          topt->m_pbox = bottomt.m_pbox;
          topt->m_type = bottomt.m_type;
          topt->m_iso = bottomt.m_iso;
        }
        topl.m_pbox = bottoml.m_pbox;
      }
    }
  }

  // build sides
  int bRev3d[4] = {0,0,1,1};
  int vid[4], eid[4];
  if( bOK ) for ( ei = 0; ei < ecount0; ei++ )
  {
    if ( bSideEdge[ei] && topeimap[ei] )
    {
      ON_BrepEdge& bottome = brep.m_E[ei];
      ON_BrepEdge& tope = brep.m_E[topeimap[ei]];
      vid[0] = bottome.m_vi[0];
      vid[1] = bottome.m_vi[1];
      vid[2] = topvimap[vid[1]];
      vid[3] = topvimap[vid[0]];
      if ( sideveimap[vid[0]] && sideveimap[vid[1]] )
      {
        ON_BrepEdge& leftedge = brep.m_E[sideveimap[vid[0]]];
        ON_BrepEdge& rightedge = brep.m_E[sideveimap[vid[1]]];
        ON_Curve* cx = bottome.DuplicateCurve();
        if ( !cx )
        {
          bOK = false;
          break;
        }
        ON_Curve* cy = leftedge.DuplicateCurve();
        if ( !cy )
        {
          delete cx;
          bOK = false;
          break;
        }
        ON_SumSurface* srf = new ON_SumSurface();
        srf->m_curve[0] = cx;
        srf->m_curve[1] = cy;
        srf->m_basepoint = srf->m_curve[1]->PointAtStart();
        srf->m_basepoint.x = -srf->m_basepoint.x;
        srf->m_basepoint.y = -srf->m_basepoint.y;
        srf->m_basepoint.z = -srf->m_basepoint.z;
        eid[0] = bottome.m_edge_index;
        eid[1] = rightedge.m_edge_index;
        eid[2] = tope.m_edge_index;
        eid[3] = leftedge.m_edge_index;
        ON_BrepFace* face = brep.NewFace(srf,vid,eid,bRev3d);
        if ( !face )
        {
          bOK = false;
          break;
        }
        else if ( bottome.m_ti.Count() == 2 )
        {
          const ON_BrepTrim& trim0 = brep.m_T[bottome.m_ti[0]];
          const ON_BrepTrim& trim1 = brep.m_T[bottome.m_ti[1]];
          const ON_BrepLoop& loop0 = brep.m_L[trim0.m_li];
          const ON_BrepLoop& loop1 = brep.m_L[trim1.m_li];
          bool bBottomFaceRev = brep.m_F[(loop0.m_fi != face->m_face_index) ? loop0.m_fi : loop1.m_fi].m_bRev;
          bool bSideFaceRev = ( trim0.m_bRev3d != trim1.m_bRev3d ) 
                            ? bBottomFaceRev 
                            : !bBottomFaceRev;
          face->m_bRev = bSideFaceRev;
        }
      }
    }
  }

  if ( !bOK )
  {
    for ( vi = brep.m_V.Count(); vi >= vcount0; vi-- )
    {
      brep.DeleteVertex(brep.m_V[vi]);
    }
  }

  return bOK;
}
// Criteria:
//
// 1.  A linear edge associated with a planar face == 0
// 2.  All linear edges associated with non-planar faces are part
//     of the same CSG shape AND all non-linear edges' non-planar faces
//     are also part of that same CSG shape = 1
// 3.  If not 2, 0
int
characterize_vert(struct subbrep_object_data *data, const ON_BrepVertex *v)
{
    std::set<int> non_planar_faces;
    std::set<int>::iterator f_it;
    std::set<struct filter_obj *> fobjs;
    std::set<struct filter_obj *>::iterator fo_it;
    struct filter_obj *control = NULL;

    for (int i = 0; i < v->m_ei.Count(); i++) {
	std::set<int> efaces;
	const ON_BrepEdge *edge = &(data->brep->m_E[v->m_ei[i]]);
	ON_Curve *tc = edge->EdgeCurveOf()->Duplicate();
	int is_linear = tc->IsLinear();
	delete tc;
	// Get the faces associated with the edge
	for (int j = 0; j < edge->TrimCount(); j++) {
	    ON_BrepTrim *trim = edge->Trim(j);
	    efaces.insert(trim->Face()->m_face_index);
	}
	for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) {
	    struct filter_obj *new_obj;
	    BU_GET(new_obj, struct filter_obj);
	    surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), new_obj);
	    if (stype == SURFACE_PLANE) {
		filter_obj_free(new_obj);
		BU_PUT(new_obj, struct filter_obj);
		if (is_linear) {
		    for (fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) {
			struct filter_obj *obj = (struct filter_obj *)(*fo_it);
			filter_obj_free(obj);
			BU_PUT(obj, struct filter_obj);
		    }
		    return 0;
		}
	    } else {
		if (!control) {
		    control = new_obj;
		} else {
		    fobjs.insert(new_obj);
		}
	    }
	}
    }

    // Can this happen?
    if (fobjs.size() == 0) {
	if (control) {
	    filter_obj_free(control);
	    BU_PUT(control, struct filter_obj);
	}
	return 0;
    }

    int equal = 1;
    for(fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) {
	if (equal && !filter_objs_equal(*fo_it, control)) equal = 0;
	struct filter_obj *obj = (struct filter_obj *)(*fo_it);
	filter_obj_free(obj);
	BU_PUT(obj, struct filter_obj);
    }
    filter_obj_free(control);
    BU_PUT(control, struct filter_obj);

    return equal;
}
Ejemplo n.º 23
0
void FindLoops(ON_Brep **b) {
    ON_3dPoint ptmatch, ptterminate, pstart, pend;
    int *curvearray;
    curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list"));
    for (int i = 0; i < (*b)->m_C3.Count(); i++) {
	curvearray[i] = -1;
    }
    ON_SimpleArray<ON_Curve *> allsegments;
    ON_SimpleArray<ON_Curve *> loopsegments;
    int loop_complete;
    for (int i = 0; i < (*b)->m_C3.Count(); i++) {
	allsegments.Append((*b)->m_C3[i]);
    }

    int allcurvesassigned = 0;
    int assignedcount = 0;
    int curvecount = 0;
    int loopcount = 0;
    while (allcurvesassigned != 1) {
	int havefirstcurve = 0;
	while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) {
	    if (curvearray[curvecount] == -1) {
		havefirstcurve = 1;
	    } else {
		curvecount++;
	    }
	}
	// First, sort through things to assign curves to loops.
	loop_complete = 0;
	while ((loop_complete != 1) && (allcurvesassigned != 1)) {
	    curvearray[curvecount] = loopcount;
	    ptmatch = (*b)->m_C3[curvecount]->PointAtEnd();
	    ptterminate = (*b)->m_C3[curvecount]->PointAtStart();
	    for (int i = 0; i < allsegments.Count(); i++) {
		pstart = (*b)->m_C3[i]->PointAtStart();
		pend = (*b)->m_C3[i]->PointAtEnd();
		if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) {
		    curvecount = i;
		    ptmatch = pend;
		    i = allsegments.Count();
		    if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) {
			loop_complete = 1;
			loopcount++;
		    }
		} else {
		    if (i == allsegments.Count() - 1) {
			loop_complete = 1; //If we reach this pass, loop had better be complete
			loopcount++;
			assignedcount = 0;
			for (int j = 0; j < allsegments.Count(); j++) {
			    if (curvearray[j] != -1) assignedcount++;
			}
			if (allsegments.Count() == assignedcount) allcurvesassigned = 1;
		    }
		}
	    }
	}
    }

    double maxdist = 0.0;
    int largest_loop_index = 0;
    for (int i = 0; i <= loopcount ; i++) {
	ON_BoundingBox lbbox;
	for (int j = 0; j < (*b)->m_C3.Count(); j++) {
	    if (curvearray[j] == i) {
		ON_Curve *currcurve = (*b)->m_C3[j];
		currcurve->GetBoundingBox(lbbox, true);
	    }
	}
	point_t minpt, maxpt;
	double currdist;
	VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]);
	VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]);
	currdist = DIST_PT_PT(minpt, maxpt);
	if (currdist > maxdist) {
	    maxdist = currdist;
	    largest_loop_index = i;
	}
    }


    for (int i = 0; i < allsegments.Count(); i++) {
	if (curvearray[i] == largest_loop_index) loopsegments.Append((*b)->m_C3[i]);
    }

    (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::outer, loopsegments, true);

    loopsegments.Empty();

    // If there's anything left, make inner loops out of it
    for (int i = 0; i <= loopcount; i++) {
	if (i != largest_loop_index) {
	    for (int j = 0; j < allsegments.Count(); j++) {
		if (curvearray[j] == i) loopsegments.Append((*b)->m_C3[j]);
	    }
	    (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::inner, loopsegments, true);
	}
	loopsegments.Empty();
    }

    bu_free(curvearray, "sketch edge list");
}
void
subbrep_planar_init(struct subbrep_object_data *data)
{
    if (!data) return;
    if (data->planar_obj) return;
    BU_GET(data->planar_obj, struct subbrep_object_data);
    subbrep_object_init(data->planar_obj, data->brep);
    bu_vls_sprintf(data->planar_obj->key, "%s", bu_vls_addr(data->key));
    data->planar_obj->obj_cnt = data->obj_cnt;
    (*data->obj_cnt)++;
    bu_vls_sprintf(data->planar_obj->name_root, "%s_%d", bu_vls_addr(data->name_root), *(data->obj_cnt));
    data->planar_obj->type = PLANAR_VOLUME;

    data->planar_obj->local_brep = ON_Brep::New();
    std::map<int, int> face_map;
    std::map<int, int> surface_map;
    std::map<int, int> edge_map;
    std::map<int, int> vertex_map;
    std::map<int, int> loop_map;
    std::map<int, int> c3_map;
    std::map<int, int> c2_map;
    std::map<int, int> trim_map;
    std::set<int> faces;
    std::set<int> fil;
    std::set<int> loops;
    std::set<int> skip_verts;
    std::set<int> skip_edges;
    std::set<int> keep_verts;
    std::set<int> partial_edges;
    std::set<int> isolated_trims;  // collect 2D trims whose parent loops aren't fully included here
    array_to_set(&faces, data->faces, data->faces_cnt);
    array_to_set(&fil, data->fil, data->fil_cnt);
    array_to_set(&loops, data->loops, data->loops_cnt);
    std::map<int, std::set<int> > face_loops;
    std::map<int, std::set<int> >::iterator fl_it;
    std::set<int>::iterator l_it;

    for (int i = 0; i < data->edges_cnt; i++) {
	int c3i;
	int new_edge_curve = 0;
	const ON_BrepEdge *old_edge = &(data->brep->m_E[data->edges[i]]);
	//std::cout << "old edge: " << old_edge->Vertex(0)->m_vertex_index << "," << old_edge->Vertex(1)->m_vertex_index << "\n";

	// See if the vertices from this edge play a role in the planar volume
	int use_edge = 2;
	for (int vi = 0; vi < 2; vi++) {
	    int vert_test = -1;
	    int vert_ind = old_edge->Vertex(vi)->m_vertex_index;
	    if (skip_verts.find(vert_ind) != skip_verts.end()) {
		vert_test = 1;
	    }
	    if (vert_test == -1 && keep_verts.find(vert_ind) != keep_verts.end()) {
		vert_test = 0;
	    }
	    if (vert_test == -1) {
		vert_test = characterize_vert(data, old_edge->Vertex(vi));
		if (vert_test) {
		    skip_verts.insert(vert_ind);
		    ON_3dPoint vp = old_edge->Vertex(vi)->Point();
		    bu_log("vert %d (%f %f %f): %d\n", vert_ind, vp.x, vp.y, vp.z, vert_test);
		} else {
		    keep_verts.insert(vert_ind);
		}
	    }
	    if (vert_test == 1) {
		use_edge--;
	    }
	}

	if (use_edge == 0) {
	    bu_log("skipping edge %d - both verts are skips\n", old_edge->m_edge_index);
	    skip_edges.insert(old_edge->m_edge_index);
	    continue;
	}

	if (use_edge == 1) {
	    bu_log("One of the verts for edge %d is a skip.\n", old_edge->m_edge_index);
	    partial_edges.insert(old_edge->m_edge_index);
	    continue;
	}

	// Get the 3D curves from the edges
	if (c3_map.find(old_edge->EdgeCurveIndexOf()) == c3_map.end()) {
	    ON_Curve *nc = old_edge->EdgeCurveOf()->Duplicate();
	    ON_Curve *tc = old_edge->EdgeCurveOf()->Duplicate();
	    if (tc->IsLinear()) {
		c3i = data->planar_obj->local_brep->AddEdgeCurve(nc);
		c3_map[old_edge->EdgeCurveIndexOf()] = c3i;
	    } else {
		ON_Curve *c3 = new ON_LineCurve(old_edge->Vertex(0)->Point(), old_edge->Vertex(1)->Point());
		c3i = data->planar_obj->local_brep->AddEdgeCurve(c3);
		c3_map[old_edge->EdgeCurveIndexOf()] = c3i;
		new_edge_curve = 1;
	    }
	} else {
	    c3i = c3_map[old_edge->EdgeCurveIndexOf()];
	}


	// Get the vertices from the edges
	int v[2];
	for (int vi = 0; vi < 2; vi++) {
	    if (vertex_map.find(old_edge->Vertex(vi)->m_vertex_index) == vertex_map.end()) {
		ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(old_edge->Vertex(vi)->Point(), old_edge->Vertex(vi)->m_tolerance);
		v[vi] = newvvi.m_vertex_index;
		vertex_map[old_edge->Vertex(vi)->m_vertex_index] = v[vi];
	    } else {
		v[vi] = vertex_map[old_edge->Vertex(vi)->m_vertex_index];
	    }
	}

	ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[v[0]], data->planar_obj->local_brep->m_V[v[1]], c3i, NULL ,0);
	edge_map[old_edge->m_edge_index] = new_edge.m_edge_index;

	// Get the 2D curves from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    if (faces.find(old_trim->Face()->m_face_index) != faces.end()) {
		if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) {
		    ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate();
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(nc);
		    c2_map[old_trim->TrimCurveIndexOf()] = c2i;
		    //std::cout << "c2i: " << c2i << "\n";
		}
	    }
	}

	// Get the faces and surfaces from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    if (face_map.find(old_trim->Face()->m_face_index) == face_map.end()) {
		if (faces.find(old_trim->Face()->m_face_index) != faces.end()) {
		    ON_Surface *ns = old_trim->Face()->SurfaceOf()->Duplicate();
		    ON_Surface *ts = old_trim->Face()->SurfaceOf()->Duplicate();
		    if (ts->IsPlanar(NULL, BREP_PLANAR_TOL)) {
			int nsid = data->planar_obj->local_brep->AddSurface(ns);
			surface_map[old_trim->Face()->SurfaceIndexOf()] = nsid;
			ON_BrepFace &new_face = data->planar_obj->local_brep->NewFace(nsid);
			face_map[old_trim->Face()->m_face_index] = new_face.m_face_index;
			//std::cout << "old face " << old_trim->Face()->m_face_index << " is now " << new_face.m_face_index << "\n";
			if (fil.find(old_trim->Face()->m_face_index) != fil.end()) {
			    data->planar_obj->local_brep->FlipFace(new_face);
			}
		    }
		}
	    }
	}

	// Get the loops from the trims
	for (int j = 0; j < old_edge->TrimCount(); j++) {
	    ON_BrepTrim *old_trim = old_edge->Trim(j);
	    ON_BrepLoop *old_loop = old_trim->Loop();
	    if (face_map.find(old_trim->Face()->m_face_index) != face_map.end()) {
		if (loops.find(old_loop->m_loop_index) != loops.end()) {
		    if (loop_map.find(old_loop->m_loop_index) == loop_map.end()) {
			face_loops[old_trim->Face()->m_face_index].insert(old_loop->m_loop_index);
		    }
		}
	    }
	}
    }
    for (fl_it = face_loops.begin(); fl_it != face_loops.end(); fl_it++) {
	int loop_cnt = fl_it->second.size();
	if (loop_cnt == 1) {
	    // If we have only one loop on a face it's an outer loop,
	    // whatever it was in the original brep.
	    const ON_BrepLoop *old_loop = &(data->brep->m_L[*(fl_it->second.begin())]);
	    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
	    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
	} else {
	    bu_log("loop_cnt: %d\n", loop_cnt);
	    // If we ended up with multiple loops, one of them should be an outer loop
	    // and the rest inner loops
	    // Get the outer loop first
	    for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) {
		const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]);
		if (data->brep->LoopDirection(data->brep->m_L[*l_it]) == 1) {
		    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
		    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
		}
	    }
	    // Now get the inner loops;
	    for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) {
		const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]);
		if (data->brep->LoopDirection(data->brep->m_L[*l_it]) != 1) {
		    ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::inner, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]);
		    loop_map[old_loop->m_loop_index] = nl.m_loop_index;
		}
	    }
	}
    }

    // Now, create new trims using the old loop definitions and the maps
    std::map<int, int>::iterator loop_it;
    std::set<int> evaluated;
    for (loop_it = loop_map.begin(); loop_it != loop_map.end(); loop_it++) {
	const ON_BrepLoop *old_loop = &(data->brep->m_L[(*loop_it).first]);
	ON_BrepLoop &new_loop = data->planar_obj->local_brep->m_L[(*loop_it).second];
	for (int j = 0; j < old_loop->TrimCount(); j++) {
	    const ON_BrepTrim *old_trim = old_loop->Trim(j);
	    ON_BrepEdge *o_edge = old_trim->Edge();
	    if (!o_edge) {
		/* If we didn't have an edge originally, we need to add the 2d curve here */
		if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) {
		    ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate();
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(nc);
		    c2_map[old_trim->TrimCurveIndexOf()] = c2i;
		}
		if (vertex_map.find(old_trim->Vertex(0)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvs = data->planar_obj->local_brep->NewVertex(old_trim->Vertex(0)->Point(), old_trim->Vertex(0)->m_tolerance);
		    vertex_map[old_trim->Vertex(0)->m_vertex_index] = newvs.m_vertex_index;
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(newvs, new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		} else {
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(data->planar_obj->local_brep->m_V[vertex_map[old_trim->Vertex(0)->m_vertex_index]], new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		}
		continue;
	    }

	    if (evaluated.find(o_edge->m_edge_index) != evaluated.end()) {
		bu_log("edge %d already handled, continuing...\n", o_edge->m_edge_index);
		continue;
	    }

	    // Don't use a trim connected to an edge we are skipping
	    if (skip_edges.find(o_edge->m_edge_index) != skip_edges.end()) {
		bu_log("edge %d is skipped, continuing...\n", o_edge->m_edge_index);
		evaluated.insert(o_edge->m_edge_index);
		continue;
	    }

	    int is_partial = 0;
	    if (partial_edges.find(o_edge->m_edge_index) != partial_edges.end()) is_partial = 1;

	    if (!is_partial) {
		ON_BrepEdge &n_edge = data->planar_obj->local_brep->m_E[edge_map[o_edge->m_edge_index]];
		ON_Curve *ec = o_edge->EdgeCurveOf()->Duplicate();
		if (ec->IsLinear()) {
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2_map[old_trim->TrimCurveIndexOf()]);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		    nt.m_iso = old_trim->m_iso;
		} else {
		    // Wasn't linear, but wasn't partial either - replace with a line
		    ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate();
		    ON_3dPoint p1 = c2_orig->PointAt(c2_orig->Domain().Min());
		    ON_3dPoint p2 = c2_orig->PointAt(c2_orig->Domain().Max());
		    ON_Curve *c2 = new ON_LineCurve(p1, p2);
		    c2->ChangeDimension(2);
		    int c2i = data->planar_obj->local_brep->AddTrimCurve(c2);
		    ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2i);
		    nt.m_tolerance[0] = old_trim->m_tolerance[0];
		    nt.m_tolerance[1] = old_trim->m_tolerance[1];
		    nt.m_iso = old_trim->m_iso;
		    delete c2_orig;
		}
		delete ec;
	    } else {
		// Partial edge - let the fun begin
		ON_3dPoint p1, p2;
		ON_BrepEdge *next_edge;
		bu_log("working a partial edge: %d\n", o_edge->m_edge_index);
		int v[2];
		v[0] = o_edge->Vertex(0)->m_vertex_index;
		v[1] = o_edge->Vertex(1)->m_vertex_index;
		// figure out which trim point we can use, the min or max
		int pos1 = 0;
		if (skip_verts.find(v[0]) != skip_verts.end()) {
		    pos1 = 1;
		}
		int j_next = j;
		ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate();
		ON_Curve *c2_next = NULL;
		int walk_dir = 1;
		// bump the loop iterator to get passed any skipped edges to
		// the next partial
		while (!c2_next) {
		    (walk_dir == 1) ? j_next++ : j_next--;
		    if (j_next == old_loop->TrimCount()) {
			j_next = 0;
		    }
		    if (j_next == -1) {
			j_next = old_loop->TrimCount() - 1;
		    }
		    const ON_BrepTrim *next_trim = old_loop->Trim(j_next);
		    next_edge = next_trim->Edge();
		    if (!next_edge) continue;
		    if (skip_edges.find(next_edge->m_edge_index) == skip_edges.end()) {
			if (partial_edges.find(next_edge->m_edge_index) != partial_edges.end()) {
			    bu_log("found next partial edge %d\n", next_edge->m_edge_index);
			    evaluated.insert(next_edge->m_edge_index);
			    c2_next = next_trim->TrimCurveOf()->Duplicate();
			} else {
			    bu_log("partial edge %d followed by non-partial %d, need to go the other way\n", o_edge->m_edge_index, next_edge->m_edge_index);
			    j_next--;
			    walk_dir = -1;
			}
		    } else {
			bu_log("skipping fully ignored edge %d\n", next_edge->m_edge_index);
			evaluated.insert(next_edge->m_edge_index);
		    }
		}
		int v2[2];
		v2[0] = next_edge->Vertex(0)->m_vertex_index;
		v2[1] = next_edge->Vertex(1)->m_vertex_index;
		// figure out which trim point we can use, the min or max
		int pos2 = 0;
		if (skip_verts.find(v2[0]) != skip_verts.end()) {
		    pos2 = 1;
		}

		int vmapped[2];
		if (vertex_map.find(o_edge->Vertex(pos1)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(o_edge->Vertex(pos1)->Point(), o_edge->Vertex(pos1)->m_tolerance);
		    vertex_map[o_edge->Vertex(pos1)->m_vertex_index] = newvvi.m_vertex_index;
		}
		if (vertex_map.find(next_edge->Vertex(pos2)->m_vertex_index) == vertex_map.end()) {
		    ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(next_edge->Vertex(pos2)->Point(), next_edge->Vertex(pos2)->m_tolerance);
		    vertex_map[next_edge->Vertex(pos2)->m_vertex_index] = newvvi.m_vertex_index;
		}

		// If walk_dir is -1, need to flip things around (I think...) the verts and trim points
		// will be swapped compared to a forward walk
		if (walk_dir == -1) {
		    vmapped[1] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index];
		    vmapped[0] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index];
		} else {
		    vmapped[0] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index];
		    vmapped[1] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index];
		}

		// New Edge curve
		ON_Curve *c3 = new ON_LineCurve(o_edge->Vertex(pos1)->Point(), next_edge->Vertex(pos2)->Point());
		int c3i = data->planar_obj->local_brep->AddEdgeCurve(c3);
		ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[vmapped[0]], data->planar_obj->local_brep->m_V[vmapped[1]], c3i, NULL ,0);

		// Again, flip if walk_dir is -1
		if (walk_dir == -1) {
		    p2 = c2_orig->PointAt(c2_orig->Domain().Min());
		    p1 = c2_next->PointAt(c2_orig->Domain().Max());
		} else {
		    p1 = c2_orig->PointAt(c2_orig->Domain().Min());
		    p2 = c2_next->PointAt(c2_orig->Domain().Max());
		}
		std::cout << "p1: " << pout(p1) << "\n";
		std::cout << "p2: " << pout(p2) << "\n";
		ON_Curve *c2 = new ON_LineCurve(p1, p2);
		c2->ChangeDimension(2);
		int c2i = data->planar_obj->local_brep->AddTrimCurve(c2);
		ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(new_edge, false, new_loop, c2i);
		nt.m_tolerance[0] = old_trim->m_tolerance[0];
		nt.m_tolerance[1] = old_trim->m_tolerance[1];
		nt.m_iso = old_trim->m_iso;
		delete c2_orig;
		delete c2_next;
	    }
	}
    }

    // If there is a possibility of a negative volume for the planar solid, do a test.
    // The only way to get a negative planar solid in this context is if that solid is
    // "inside" a non-planar shape (it would be "part of" the parent shape if it were
    // planar and it would be a separate shape altogether if it were not topologically
    // connected.  So we take one partial edge, find its associated non-planar faces,
    // and collect all the partial and skipped edges from that face and any non-planar
    // faces associated with the other partial/skipped edges.
    //
    // TODO - We still have an unhandled possibility here - the self-intersecting
    // planar_obj.  For example:
    //
    //           *                *
    //       *       *        *       *
    //     *     *      *   *    *      *
    //    *     * *      * *    * *      *
    //   *     *   *           *   *      *
    //   * *  *     * * * * * *     *  *  *
    //
    if (partial_edges.size() > 0) {
	std::queue<int> connected_faces;
	std::set<int> relevant_edges;
	std::set<int>::iterator re_it;
	std::set<int> efaces;
	std::set<int>::iterator f_it;
	std::set<int> found_faces;
	const ON_BrepEdge *seed_edge = &(data->brep->m_E[*partial_edges.begin()]);
	for (int j = 0; j < seed_edge->TrimCount(); j++) {
	    ON_BrepTrim *trim = seed_edge->Trim(j);
	    efaces.insert(trim->Face()->m_face_index);
	}
	for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) {
	    surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), NULL);
	    if (stype != SURFACE_PLANE) {
		connected_faces.push(data->brep->m_F[*f_it].m_face_index);
	    }
	}
	while (!connected_faces.empty()) {
	    int face_index = connected_faces.front();
	    connected_faces.pop();
	    std::set<int> local_edges;
	    std::set<int>::iterator le_it;
	    found_faces.insert(face_index);
	    const ON_BrepFace *face = &(data->brep->m_F[face_index]);
	    const ON_BrepLoop *loop = NULL;
	    // Find the loop in this face that is associated with this subbrep
	    for (int i = 0; i < face->LoopCount(); i++) {
		int loop_ind = face->Loop(i)->m_loop_index;
		if (loops.find(loop_ind) != loops.end()) {
		    loop = &(data->brep->m_L[loop_ind]);
		    break;
		}
	    }
	    // Collect the edges that are partial or skipped
	    for (int i = 0; i < loop->TrimCount(); i++) {
		const ON_BrepTrim *trim = loop->Trim(i);
		ON_BrepEdge *edge = trim->Edge();
		if (edge) {
		    if (partial_edges.find(edge->m_edge_index) != partial_edges.end()) {
			relevant_edges.insert(edge->m_edge_index);
			local_edges.insert(edge->m_edge_index);
		    }
		    if (skip_edges.find(edge->m_edge_index) != skip_edges.end()) {
			relevant_edges.insert(edge->m_edge_index);
			local_edges.insert(edge->m_edge_index);
		    }
		}
	    }
	    // For each collected partial/skipped edge, add any faces not already
	    // found to the queue.
	    for (le_it = local_edges.begin(); le_it != local_edges.end(); le_it++) {
		const ON_BrepEdge *edge = &(data->brep->m_E[*le_it]);
		for (int j = 0; j < edge->TrimCount(); j++) {
		    ON_BrepTrim *trim = edge->Trim(j);
		    if (found_faces.find(trim->Face()->m_face_index) == found_faces.end()) {
			found_faces.insert(trim->Face()->m_face_index);
			connected_faces.push(trim->Face()->m_face_index);
		    }
		}
	    }
	}
	// Build two bounding boxes - one with the new verts in planar_obj, and the other with
	// the edges found above.
	ON_BoundingBox pbb, ebb;
	ON_MinMaxInit(&pbb.m_min, &pbb.m_max);
	ON_MinMaxInit(&ebb.m_min, &ebb.m_max);
	for (int i = 0; i < data->planar_obj->local_brep->m_V.Count(); i++) {
	    const ON_BrepVertex *v = &(data->planar_obj->local_brep->m_V[i]);
	    pbb.Set(v->Point(), true);
	}
	for (re_it = relevant_edges.begin(); re_it != relevant_edges.end(); re_it++) {
	    const ON_BrepEdge *e = &(data->brep->m_E[*re_it]);
	    ON_BoundingBox cbb = e->EdgeCurveOf()->BoundingBox();
	    ebb.Set(cbb.m_min, true);
	    ebb.Set(cbb.m_max, true);
	}
	//std::cout << "in pbb.s rpp " << pout(pbb.m_min) << " " << pout(pbb.m_max) << "\n";
	//std::cout << "in ebb.s rpp " << pout(ebb.m_min) << " " << pout(ebb.m_max) << "\n";

	if (ebb.Includes(pbb)) {
	    bu_log("negative volume\n");
	    data->planar_obj->negative_shape = -1;
	} else {
	    bu_log("positive volume\n");
	    data->planar_obj->negative_shape = 1;
	}
	data->planar_obj->params->bool_op = (data->planar_obj->negative_shape == -1) ? '-' : 'u';
    }

    // Need to preserve the vertex map for this, since we're not done building up the brep
    map_to_array(&(data->planar_obj->planar_obj_vert_map), &(data->planar_obj->planar_obj_vert_cnt), &vertex_map);

    data->planar_obj->local_brep->SetTrimTypeFlags(true);

}
Ejemplo n.º 25
0
void FindLoops(ON_Brep **b, const ON_Line* revaxis, const fastf_t ang) {
    ON_3dPoint ptmatch, ptterminate, pstart, pend;

    int *curvearray;
    curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list"));
    for (int i = 0; i < (*b)->m_C3.Count(); i++) {
	curvearray[i] = -1;
    }
    ON_SimpleArray<ON_Curve *> allsegments;
    ON_SimpleArray<ON_Curve *> loopsegments;
    int loop_complete;
    for (int i = 0; i < (*b)->m_C3.Count(); i++) {
	allsegments.Append((*b)->m_C3[i]);
    }

    int allcurvesassigned = 0;
    int assignedcount = 0;
    int curvecount = 0;
    int loopcount = 0;
    while (allcurvesassigned != 1) {
	int havefirstcurve = 0;
	while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) {
	    if (curvearray[curvecount] == -1) {
		havefirstcurve = 1;
	    } else {
		curvecount++;
	    }
	}
	// First, sort through things to assign curves to loops.
	loop_complete = 0;
	while ((loop_complete != 1) && (allcurvesassigned != 1)) {
	    curvearray[curvecount] = loopcount;
	    ptmatch = (*b)->m_C3[curvecount]->PointAtEnd();
	    ptterminate = (*b)->m_C3[curvecount]->PointAtStart();
	    for (int i = 0; i < allsegments.Count(); i++) {
		pstart = (*b)->m_C3[i]->PointAtStart();
		pend = (*b)->m_C3[i]->PointAtEnd();
		if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) {
		    curvecount = i;
		    ptmatch = pend;
		    i = allsegments.Count();
		    if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) {
			loop_complete = 1;
			loopcount++;
		    }
		} else {
		    if (i == allsegments.Count() - 1) {
			loop_complete = 1; //If we reach this pass, loop had better be complete
			loopcount++;
			assignedcount = 0;
			for (int j = 0; j < allsegments.Count(); j++) {
			    if (curvearray[j] != -1) assignedcount++;
			}
			if (allsegments.Count() == assignedcount) allcurvesassigned = 1;
		    }
		}
	    }
	}
    }

    double maxdist = 0.0;
    int largest_loop_index = 0;
    for (int i = 0; i <= loopcount ; i++) {
	ON_BoundingBox lbbox;
	for (int j = 0; j < (*b)->m_C3.Count(); j++) {
	    if (curvearray[j] == i) {
		ON_Curve *currcurve = (*b)->m_C3[j];
		currcurve->GetBoundingBox(lbbox, true);
	    }
	}
	point_t minpt, maxpt;
	double currdist;
	VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]);
	VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]);
	currdist = DIST_PT_PT(minpt, maxpt);
	if (currdist > maxdist) {
	    maxdist = currdist;
	    largest_loop_index = i;
	}
    }

    for (int i = 0; i < loopcount ; i++) {
	ON_PolyCurve* poly_curve = new ON_PolyCurve();
	for (int j = 0; j < allsegments.Count(); j++) {
	    if (curvearray[j] == i) {
		 poly_curve->Append(allsegments[j]);
	    }
	}

	ON_NurbsCurve *revcurve = ON_NurbsCurve::New();
	poly_curve->GetNurbForm(*revcurve);
	ON_RevSurface* revsurf = ON_RevSurface::New();
	revsurf->m_curve = revcurve;
	revsurf->m_axis = *revaxis;
	revsurf->m_angle = ON_Interval(0, ang);
	ON_BrepFace *face = (*b)->NewFace(*revsurf);

	if (i == largest_loop_index) {
	    (*b)->FlipFace(*face);
	}
    }

    bu_free(curvearray, "sketch edge list");
}
Ejemplo n.º 26
0
int
main(int, char**)
{
    srand(time(0));

    ON_3dPoint center(0.0, 0.0, 0.0);
    double radius = 10.0;
    ON_Sphere sphere(center, radius);
    ON_Brep *brep = ON_BrepSphere(sphere);

    ON_3dPoint p1(0.0, 0.0, 0.0);
    ON_3dPoint p2(0.0, 0.0, radius);

    // Point-point intersection
    bu_log("*** Point-point intersection ***\n");
    test_ppi(p1, p1);
    test_ppi(p1, p2);

    // Point-curve intersection
    bu_log("*** Point-curve intersection ***\n");
    // brep->m_C3[0] is an arc curve that starts from (0, 0, -R)
    // to (0, 0, R) through (R, 0, 0) which forms a semicircle.
    ON_Curve *curve = brep->m_C3[0];

    ON_3dPoint mid = curve->PointAt(curve->Domain().Mid());
    bu_log("debug: %f %f %f\n", mid[0], mid[1], mid[2]);

    bu_log("** Part 1 **\n");
    test_pci(p1, *curve);
    test_pci(p2, *curve);

    // Now we use some randomized points (should intersect)
    bu_log("** Part 2 **\n");
    for (int i = 0; i < 10; i++) {
	double x = rand_f(0.0, radius);
	double y = 0.0;
	double z = sqrt(radius*radius-x*x);
	if (rand() % 2) z = -z; // sometimes we have it negative
	ON_3dPoint test_pt(x, y, z);
	test_pci(test_pt, *curve);
    }

    // More randomize points (maybe no intersection)
    bu_log("** Part 3 **\n");
    for (int i = 0; i < 10; i++) {
	// We use test points randomly distributed inside a cube
	// from (-R, -R, -R) to (R, R, R)
	double x = rand_f(-radius, radius);
	double y = rand_f(-radius, radius);
	double z = rand_f(-radius, radius);
	ON_3dPoint test_pt(x, y, z);
	test_pci(test_pt, *curve);
    }

    // Point-surface intersection
    bu_log("*** Point-surface intersection ***\n");
    bu_log("** Part 1 **\n");
    ON_Surface *surf = brep->m_S[0];
    test_psi(p1, *surf);
    test_psi(p2, *surf);

    // Now we use some randomized points (should intersect)
    bu_log("** Part 2 **\n");
    for (int i = 0; i < 10; i++) {
	double x = rand_f(-radius, radius);
	double y_range = sqrt(radius*radius-x*x);
	double y = rand_f(-y_range, y_range);
	double z = sqrt(y_range*y_range-y*y);
	if (rand() % 2) z = -z; // sometimes we have it negative
	ON_3dPoint test_pt(x, y, z);
	test_psi(test_pt, *surf);
    }

    // More randomize points (maybe no intersection)
    bu_log("** Part 3 **\n");
    for (int i = 0; i < 10; i++) {
	// We use test points randomly distributed inside a cube
	// from (-R, -R, -R) to (R, R, R)
	double x = rand_f(-radius, radius);
	double y = rand_f(-radius, radius);
	double z = rand_f(-radius, radius);
	ON_3dPoint test_pt(x, y, z);
	test_psi(test_pt, *surf);
    }

    delete brep;
    bu_log("All finished.\n");
    return 0;
}
Ejemplo n.º 27
0
// Add the isocurves of a BrepFace to the partial boundingbox result.
static void ON_Brep_GetTightIsoCurveBoundingBox_Helper( const TL_Brep& tlbrep, const ON_BrepFace& face, ON_BoundingBox& bbox, const ON_Xform* xform, int dir )
{
  ON_Interval domain = face.Domain(1 - dir);
  int degree =         face.Degree(1 - dir);
  int spancount =      face.SpanCount(1 - dir);
  int spansamples =    degree * (degree + 1) - 1;
  if( spansamples < 2 )
    spansamples = 2;

  // pbox delineates the extremes of the face interior.
  // We can use it to trivially reject spans and isocurves.
  ON_BrepLoop* pOuterLoop = face.OuterLoop();
  if( NULL==pOuterLoop )
    return;

  const ON_BoundingBox& pbox = pOuterLoop->m_pbox;
  double t0 = ((dir == 0) ? pbox.Min().y : pbox.Min().x);
  double t1 = ((dir == 0) ? pbox.Max().y : pbox.Max().x);

  // Get the surface span vector.
  ON_SimpleArray<double> spanvector(spancount + 1);
  spanvector.SetCount(spancount + 1);
  face.GetSpanVector(1 - dir, spanvector.Array());

  // Generate a list of all the sampling parameters.
  ON_SimpleArray<double> samples(spancount * spansamples);
  for( int s = 0; s < spancount; s++)
  {
    double s0 = spanvector[s];
    double s1 = spanvector[s+1];

    // Reject span if it does not intersect the pbox.
    if( s1 < t0 ) { continue; }
    if( s0 > t1 ) { continue; }
    
    ON_Interval span(s0, s1);
    for( int i = 1; i < spansamples; i++ )
    {
      double t = span.ParameterAt((double)i / (double)(spansamples - 1));
      // Reject iso if it does not intersect the pbox.
      if( t < t0 )
        continue;
      if( t > t1 )
        break;
      samples.Append(t);
    }
  }

  //Iterate over samples
  int sample_count = samples.Count();
  ON_BoundingBox loose_box;
  ON_SimpleArray<ON_Interval> intervals;
  ON_NurbsCurve isosubcrv;

  for( int i = 0; i<sample_count; i++)
  {
    // Retrieve iso-curve.
    ON_Curve* isocrv = face.IsoCurve(dir, samples[i]);

    while( NULL!=isocrv )
    {
      // Transform isocurve if necessary, this is better than transforming downstream boundingboxes.
      if( xform )
        isocrv->Transform(*xform);

      // Compute loose box.
      if( !isocrv->GetBoundingBox(loose_box, false))
        break;

      // Determine whether the loose box is already contained within the partial result.
      if( bbox.Includes(loose_box, false) ) 
        break;

      // Solve trimming domains for the iso-curve.
      intervals.SetCount(0);
      if( !tlbrep.GetIsoIntervals(face, dir, samples[i], intervals))
        break;

      // Iterate over trimmed iso-curves.
      int interval_count = intervals.Count();
      for( int k=0; k<interval_count; k++ )
      {
        //this to mask a bug in Rhino4. GetNurbForm does not destroy the Curve Tree. It does now.
        isosubcrv.DestroyCurveTree();
        isocrv->GetNurbForm(isosubcrv, 0.0, &intervals[k]);
        ON_Brep_GetTightCurveBoundingBox_Helper(isosubcrv, bbox, NULL, NULL);
      }
      break;
    }

    if( isocrv )
    {
      delete isocrv;
      isocrv = NULL;
    }
  }
}
Ejemplo n.º 28
0
bool ON_Brep::SplitKinkyEdge( 
  int edge_index, 
  double kink_tol_radians
  )
{
  // Default kink_tol_radians MUST BE ON_PI/180.0.
  //
  // The default kink tol must be kept in sync with the default for 
  // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace().
  // See comments in TL_Brep::SplitKinkyFace() for more details.

  bool rc = true;
  if (kink_tol_radians < ON_ZERO_TOLERANCE) 
    kink_tol_radians = ON_ZERO_TOLERANCE;
  else if (kink_tol_radians > ON_PI - ON_ZERO_TOLERANCE) 
    kink_tol_radians = ON_PI - ON_ZERO_TOLERANCE;
  double atol = cos(kink_tol_radians);
  if (edge_index < 0 || edge_index >= m_E.Count()) 
    return false;
  ON_BrepEdge& E = m_E[edge_index];
  if (E.m_c3i < 0) 
    return false;
  ON_SimpleArray<double> split_t(4);
  double t0 = E.Domain()[0];
  int hint = 0;
  ON_Curve* curve = m_C3[E.m_c3i];
  if (!curve) return false;
  int scount = curve->SpanCount();
  while (split_t.Count() < scount){
    double t;
    if (!E.GetNextDiscontinuity(ON::G1_continuous, t0, E.Domain()[1], 
      &t, &hint, NULL, atol)) break;
    split_t.Append(t);
    t0 = t;
  }
  if (split_t.Count() >= scount) 
    return false;

  if (split_t.Count() == 0) 
    return true;//no kinks

  split_t.Reverse();
  for (int i=0; i<split_t.Count(); i++){
    //if split parameter is near start or end, just adjust domain.
    double t0, t1;
    m_E[edge_index].GetDomain(&t0, &t1);
    if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) continue;

    //6 Dec 2002 Dale Lear:
    //   I added the relative edge_split_s and trm_split_s tests to detect
    //   attempts to trim a nano-gnats-wisker of the end of a trim.

    // set to true if edge should be trimmed instead of split.
    bool bTrimEdgeEnd = false; 

    double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]);
    double trim_split_s = 0.5;

    if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON )
    {
      continue;
    }
    if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON)
    {
      continue;
    }

    // trim_t[] = corresponding trim parameters
    ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count());


    if ( !bTrimEdgeEnd )
    {
      for (int j=0; j<m_E[edge_index].m_ti.Count(); j++)
      {
        double t;
        if (!GetTrimParameter(m_E[edge_index].m_ti[j], split_t[i], &t)){
          rc = false;
          continue;
        }
        trim_t.Append(t);
        const ON_BrepTrim& trim = m_T[m_E[edge_index].m_ti[j]];
        ON_Interval trim_domain = trim.Domain();
        trim_split_s = trim_domain.NormalizedParameterAt(t);
        if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE )
        {
          bTrimEdgeEnd = true;
          break;
        }
        if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE )
        {
          bTrimEdgeEnd = true;
          break;
        }
      }
    }

    if ( bTrimEdgeEnd )
    {
      // if we get here, a split parameter we got was too close to
      // the end of the edge or a trim for us to split it.
      if ( edge_split_s <= 0.01 )
      {
        if ( t0 < split_t[i] )
          m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(split_t[i], t1));
      }
      else if ( edge_split_s >= 0.99 )
      {
        if ( split_t[i] < t1 )
          m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(t0, split_t[i]));
      }
      else
      {
        // no decent agreement between trims and edges - continue
        // with other parameters but this is basically the same
        // thing as having SplitEdge() fail.
        rc = false;
      }

      continue;
    }

    if (!SplitEdge(edge_index, split_t[i], trim_t)){
      rc = false;
      continue;
    }
    ON_Curve* new_curve0 = m_E[edge_index].DuplicateCurve();
    if (new_curve0){
      m_E[edge_index].m_c3i = AddEdgeCurve(new_curve0);
      m_E[edge_index].SetProxyCurve(new_curve0);
    }
    ON_Curve* new_curve1 = m_E.Last()->DuplicateCurve();
    if (new_curve1){
      m_E.Last()->m_c3i = AddEdgeCurve(new_curve1);
      m_E.Last()->SetProxyCurve(new_curve1);
    }
  }

  return rc;
}