// 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); }
// 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; } } }
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; }
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 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"); }