Esempio n. 1
0
void genInitialVars()
{
	curve.closed = true;
	curve.nVertices = 64;
	curve.restAngles.resize(curve.nVertices);
	curve.restLengths.resize(curve.nVertices);

	resize(vars, curve.nVertices);
	resize(initialVars, curve.nVertices);

	const double R = 1.7;
	const double phi = 2.0 * PI / curve.nVertices;
	const double restL = 2.0 * R * sin(phi * 0.5);

	params.refLength = restL;

	for(int i=0; i<curve.nVertices; i++)
	{
		curve.restAngles(i) = PI;
		curve.restLengths(i) = restL;

		const double theta = 2.0 * PI * i / curve.nVertices;
		//const double _r = R * ((i%2 == 0) ? 0.7 : 1.3);
		const double _r = R;
		vars.pos(0, i) = _r * cos(theta);
		vars.pos(1, i) = _r * sin(theta);
		vars.conf(i) = 0.0;
	}

	initialVars = vars;

	initSolverVars(&params, &curve, initialVars, solverVars);
}
Esempio n. 2
0
void FitSCurve(char *dirName, int roc, int col, int row)
{
	gSystem->Load("../psi46expert/.libs/libpsi46ana.so");
	
	SCurve sCurve;
	sCurve.FitSCurve(dirName, roc, col, row);
}
Esempio n. 3
0
void FitSCurves(char *dirName)
{
        gSystem->Load("libMinuit.so");
	gSystem->Load("../psi46expert/.libs/libpsi46ana.so");
	
	SCurve sCurve;
	sCurve.FitSCurves(dirName);
}
Esempio n. 4
0
void SShell::Clear(void) {
    SSurface *s;
    for(s = surface.First(); s; s = surface.NextAfter(s)) {
        s->Clear();
    }
    surface.Clear();

    SCurve *c;
    for(c = curve.First(); c; c = curve.NextAfter(c)) {
        c->Clear();
    }
    curve.Clear();
}
Esempio n. 5
0
void SShell::CopyCurvesSplitAgainst(bool opA, SShell *agnst, SShell *into) {
    SCurve *sc;
    for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
        SCurve scn = sc->MakeCopySplitAgainst(agnst, NULL,
                                surface.FindById(sc->surfA),
                                surface.FindById(sc->surfB));
        scn.source = opA ? SCurve::FROM_A : SCurve::FROM_B;

        hSCurve hsc = into->curve.AddAndAssignId(&scn);
        // And note the new ID so that we can rewrite the trims appropriately
        sc->newH = hsc;
    }
}
//Curve curve intersection
void CIntersect::recurse_intersect(const SCurve &left, const SCurve &right, int depth)
{
	//reject curves that do not overlap with bounding boxes
	if(!intersect(left.aabb,right.aabb)) return;

	//accept curves (and perform super detailed check for intersections)
	//if the values are below tolerance

	//NOTE FOR BETTERING OF ALGORITHM: SHOULD ALSO/IN-PLACE-OF CHECK MAGNITUDE OF EDGES (or approximate)
	if(depth >= max_depth)
	{
		//NOTE FOR IMPROVEMENT: Polish roots based on original curve with the Jacobian
		//						(may be too expensive to be effective)

		//perform root approximation
		//collide line segments

		float t,s;

		for(int i = 0; i < 3; ++i)
		{
			for(int j = 0; j < 3; ++j)
			{
				//intersect line segments
				if(intersect_line_segments(left.b[i],left.b[i+1],t,right.b[j],right.b[j+1],s))
				{
					//We got one Jimmy
					times.push_back(intersect_set::value_type(t,s));
				}
			}
		}

		return;
	}

	//NOTE FOR IMPROVEMENT: only subdivide one curve and choose the one that has
	//						the highest approximated length
	//fast approximation to curve length may be hard (accurate would
	// involve 3 square roots), could sum the squares which would be
	// quick but inaccurate

	SCurve l1,r1,l2,r2;
	left.Split(l1,r1);	//subdivide left
	right.Split(l2,r2); //subdivide right

	//Test each candidate against each other
	recurse_intersect(l1,l2);
	recurse_intersect(l1,r2);
	recurse_intersect(r1,l2);
	recurse_intersect(r1,r2);
}
Esempio n. 7
0
void SSurface::EdgeNormalsWithinSurface(Point2d auv, Point2d buv,
                                        Vector *pt,
                                        Vector *enin, Vector *enout,
                                        Vector *surfn,
                                        uint32_t auxA,
                                        SShell *shell, SShell *sha, SShell *shb)
{
    // the midpoint of the edge
    Point2d muv  = (auv.Plus(buv)).ScaledBy(0.5);

    *pt    = PointAt(muv);

    // If this edge just approximates a curve, then refine our midpoint so
    // so that it actually lies on that curve too. Otherwise stuff like
    // point-on-face tests will fail, since the point won't actually lie
    // on the other face.
    hSCurve hc = { auxA };
    SCurve *sc = shell->curve.FindById(hc);
    if(sc->isExact && sc->exact.deg != 1) {
        double t;
        sc->exact.ClosestPointTo(*pt, &t, false);
        *pt = sc->exact.PointAt(t);
        ClosestPointTo(*pt, &muv);
    } else if(!sc->isExact) {
        SSurface *trimmedA = sc->GetSurfaceA(sha, shb),
                 *trimmedB = sc->GetSurfaceB(sha, shb);
        *pt = trimmedA->ClosestPointOnThisAndSurface(trimmedB, *pt);
        ClosestPointTo(*pt, &muv);
    }

    *surfn = NormalAt(muv.x, muv.y);

    // Compute the edge's inner normal in xyz space.
    Vector ab    = (PointAt(auv)).Minus(PointAt(buv)),
           enxyz = (ab.Cross(*surfn)).WithMagnitude(SS.ChordTolMm());
    // And based on that, compute the edge's inner normal in uv space. This
    // vector is perpendicular to the edge in xyz, but not necessarily in uv.
    Vector tu, tv;
    TangentsAt(muv.x, muv.y, &tu, &tv);
    Point2d enuv;
    enuv.x = enxyz.Dot(tu) / tu.MagSquared();
    enuv.y = enxyz.Dot(tv) / tv.MagSquared();

    // Compute the inner and outer normals of this edge (within the srf),
    // in xyz space. These are not necessarily antiparallel, if the
    // surface is curved.
    Vector pin   = PointAt(muv.Minus(enuv)),
           pout  = PointAt(muv.Plus(enuv));
    *enin  = pin.Minus(*pt),
    *enout = pout.Minus(*pt);
}
Esempio n. 8
0
void Surf::PlaneBorderCurveIntersect( Surf* surfPtr, SCurve* brdPtr )
{
    bool repeat_curve = false;
    bool null_ICurve = false;
    if ( brdPtr->GetICurve() != NULL )
    {
        for ( int j = 0 ; j < (int)m_SCurveVec.size() ; j++ )
        {
            if ( brdPtr->GetICurve() == m_SCurveVec[j]->GetICurve() )
            {
                repeat_curve = true;
            }
        }
    }
    else
    {
        null_ICurve = true;
    }

    if ( !repeat_curve )
    {
        SCurve* pSCurve = new SCurve;
        SCurve* bSCurve = new SCurve;
        ICurve* pICurve = new ICurve;

        ICurve* bICurve = pICurve;
        ICurve* obICurve = brdPtr->GetICurve();

        vector< ICurve* > ICurves = CfdMeshMgr.GetICurveVec();
        int ICurveVecIndex;

        Bezier_curve crv = brdPtr->GetUWCrv();
        crv.UWCurveToXYZCurve( surfPtr );
        crv.XYZCurveToUWCurve( this );
        pSCurve->SetUWCrv( crv );

        pICurve->m_SCurve_A = brdPtr;
        pICurve->m_SCurve_B = pSCurve;
        pICurve->m_PlaneBorderIntersectFlag = true;
        pSCurve->SetSurf( this );
        pSCurve->SetICurve( pICurve );

        bICurve->m_SCurve_A = pSCurve;
        bICurve->m_SCurve_B = brdPtr;
        bICurve->m_PlaneBorderIntersectFlag = true;
        bSCurve->SetSurf( surfPtr );
        bSCurve->SetICurve( bICurve );

        brdPtr->SetICurve( bICurve );

        if ( !null_ICurve )
        {
            ICurveVecIndex = distance( ICurves.begin(), find( ICurves.begin(), ICurves.end(), obICurve ) );
            if ( ICurveVecIndex < (int)ICurves.size() )
            {
                CfdMeshMgr.SetICurveVec( brdPtr->GetICurve(), ICurveVecIndex );
            }
        }
        else
        {
            for ( int i = 0 ; i < (int)ICurves.size() ; i++ )
            {
                if ( ICurves[i]->m_SCurve_A == brdPtr && ICurves[i]->m_SCurve_B == NULL )
                {
                    ICurves[i]->m_SCurve_B = pSCurve;
                    ICurves[i]->m_PlaneBorderIntersectFlag = true;
                }
            }
        }

        m_SCurveVec.push_back( pSCurve );
    }
}
Esempio n. 9
0
void Surf::FindBorderCurves()
{
    double degen_tol = 0.000001;

    //==== Load 4 Border Curves if Not Degenerate ====//
    SCurve* scrv;
    double min_u = m_SurfCore.GetMinU();
    double min_w = m_SurfCore.GetMinW();
    double max_u = m_SurfCore.GetMaxU();
    double max_w = m_SurfCore.GetMaxW();

    vector< vec3d > pnts;
    pnts.resize( 2 );

    pnts[0].set_xyz( min_u, min_w, 0 );         // Inc U
    pnts[1].set_xyz( max_u, min_w, 0 );

    scrv = new SCurve( this );
    scrv->BuildBezierCurve( pnts, 0.25 );

    if ( scrv->Length( 10 ) > degen_tol )
    {
        m_SCurveVec.push_back( scrv );
    }
    else
    {
        delete scrv;
    }

    pnts[0].set_xyz( max_u, min_w, 0 );       // Inc W
    pnts[1].set_xyz( max_u, max_w, 0 );

    scrv = new SCurve( this );
    scrv->BuildBezierCurve( pnts, 0.25 );

    if ( scrv->Length( 10 ) > degen_tol )
    {
        m_SCurveVec.push_back( scrv );
    }
    else
    {
        delete scrv;
    }

    pnts[0].set_xyz( max_u, max_w, 0 );         // Dec U
    pnts[1].set_xyz( min_u, max_w, 0 );

    scrv = new SCurve( this );
    scrv->BuildBezierCurve( pnts, 0.25 );

    if ( scrv->Length( 10 ) > degen_tol )
    {
        m_SCurveVec.push_back( scrv );
    }
    else
    {
        delete scrv;
    }

    pnts[0].set_xyz( min_u, max_w,   0 );           // Dec W
    pnts[1].set_xyz( min_u, min_w,       0 );

    scrv = new SCurve( this );
    scrv->BuildBezierCurve( pnts, 0.25 );

    if ( scrv->Length( 10 ) > degen_tol )
    {
        m_SCurveVec.push_back( scrv );
    }
    else
    {
        delete scrv;
    }
}
Esempio n. 10
0
void SCurve_2(){
    gSystem->Load("../psi46expert/.libs/libpsi46ana.so");
	
	SCurve sCurve;
        sCurve.FitSCurves("../psi46expert/currentModule/");
       } 
Esempio n. 11
0
void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB,
                                         SShell *agnstA, SShell *agnstB, SShell *into)
{
    SCurve sc = {};
    // Important to keep the order of (surfA, surfB) consistent; when we later
    // rewrite the identifiers, we rewrite surfA from A and surfB from B.
    sc.surfA = h;
    sc.surfB = srfB->h;
    sc.exact = *sb;
    sc.isExact = true;

    // Now we have to piecewise linearize the curve. If there's already an
    // identical curve in the shell, then follow that pwl exactly, otherwise
    // calculate from scratch.
    SCurve split, *existing = NULL, *se;
    SBezier sbrev = *sb;
    sbrev.Reverse();
    bool backwards = false;
    for(se = into->curve.First(); se; se = into->curve.NextAfter(se)) {
        if(se->isExact) {
            if(sb->Equals(&(se->exact))) {
                existing = se;
                break;
            }
            if(sbrev.Equals(&(se->exact))) {
                existing = se;
                backwards = true;
                break;
            }
        }
    }
    if(existing) {
        SCurvePt *v;
        for(v = existing->pts.First(); v; v = existing->pts.NextAfter(v)) {
            sc.pts.Add(v);
        }
        if(backwards) sc.pts.Reverse();
        split = sc;
        sc = {};
    } else {
        sb->MakePwlInto(&(sc.pts));
        // and split the line where it intersects our existing surfaces
        split = sc.MakeCopySplitAgainst(agnstA, agnstB, this, srfB);
        sc.Clear();
    }

    // Test if the curve lies entirely outside one of the
    SCurvePt *scpt;
    bool withinA = false, withinB = false;
    for(scpt = split.pts.First(); scpt; scpt = split.pts.NextAfter(scpt)) {
        double tol = 0.01;
        Point2d puv;
        ClosestPointTo(scpt->p, &puv);
        if(puv.x > -tol && puv.x < 1 + tol &&
           puv.y > -tol && puv.y < 1 + tol)
        {
            withinA = true;
        }
        srfB->ClosestPointTo(scpt->p, &puv);
        if(puv.x > -tol && puv.x < 1 + tol &&
           puv.y > -tol && puv.y < 1 + tol)
        {
            withinB = true;
        }
        // Break out early, no sense wasting time if we already have the answer.
        if(withinA && withinB) break;
    }
    if(!(withinA && withinB)) {
        // Intersection curve lies entirely outside one of the surfaces, so
        // it's fake.
        split.Clear();
        return;
    }

#if 0
    if(sb->deg == 2) {
        dbp(" ");
        SCurvePt *prev = NULL, *v;
        dbp("split.pts.n = %d", split.pts.n);
        for(v = split.pts.First(); v; v = split.pts.NextAfter(v)) {
            if(prev) {
                Vector e = (prev->p).Minus(v->p).WithMagnitude(0);
                SS.nakedEdges.AddEdge((prev->p).Plus(e), (v->p).Minus(e));
            }
            prev = v;
        }
    }
#endif // 0
    ssassert(!(sb->Start()).Equals(sb->Finish()),
             "Unexpected zero-length edge");

    split.source = SCurve::Source::INTERSECTION;
    into->curve.AddAndAssignId(&split);
}
Esempio n. 12
0
void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
                                SShell *into)
{
    Vector amax, amin, bmax, bmin;
    GetAxisAlignedBounding(&amax, &amin);
    b->GetAxisAlignedBounding(&bmax, &bmin);

    if(Vector::BoundingBoxesDisjoint(amax, amin, bmax, bmin)) {
        // They cannot possibly intersect, no curves to generate
        return;
    }

    Vector alongt, alongb;
    SBezier oft, ofb;
    bool isExtdt = this->IsExtrusion(&oft, &alongt),
         isExtdb =    b->IsExtrusion(&ofb, &alongb);

    if(degm == 1 && degn == 1 && b->degm == 1 && b->degn == 1) {
        // Line-line intersection; it's a plane or nothing.
        Vector na = NormalAt(0, 0).WithMagnitude(1),
               nb = b->NormalAt(0, 0).WithMagnitude(1);
        double da = na.Dot(PointAt(0, 0)),
               db = nb.Dot(b->PointAt(0, 0));

        Vector dl = na.Cross(nb);
        if(dl.Magnitude() < LENGTH_EPS) return; // parallel planes
        dl = dl.WithMagnitude(1);
        Vector p = Vector::AtIntersectionOfPlanes(na, da, nb, db);

        // Trim it to the region 0 <= {u,v} <= 1 for each plane; not strictly
        // necessary, since line will be split and excess edges culled, but
        // this improves speed and robustness.
        int i;
        double tmax = VERY_POSITIVE, tmin = VERY_NEGATIVE;
        for(i = 0; i < 2; i++) {
            SSurface *s = (i == 0) ? this : b;
            Vector tu, tv;
            s->TangentsAt(0, 0, &tu, &tv);

            double up, vp, ud, vd;
            s->ClosestPointTo(p, &up, &vp);
            ud = (dl.Dot(tu)) / tu.MagSquared();
            vd = (dl.Dot(tv)) / tv.MagSquared();

            // so u = up + t*ud
            //    v = vp + t*vd
            if(ud > LENGTH_EPS) {
                tmin = max(tmin, -up/ud);
                tmax = min(tmax, (1 - up)/ud);
            } else if(ud < -LENGTH_EPS) {
                tmax = min(tmax, -up/ud);
                tmin = max(tmin, (1 - up)/ud);
            } else {
                if(up < -LENGTH_EPS || up > 1 + LENGTH_EPS) {
                    // u is constant, and outside [0, 1]
                    tmax = VERY_NEGATIVE;
                }
            }
            if(vd > LENGTH_EPS) {
                tmin = max(tmin, -vp/vd);
                tmax = min(tmax, (1 - vp)/vd);
            } else if(vd < -LENGTH_EPS) {
                tmax = min(tmax, -vp/vd);
                tmin = max(tmin, (1 - vp)/vd);
            } else {
                if(vp < -LENGTH_EPS || vp > 1 + LENGTH_EPS) {
                    // v is constant, and outside [0, 1]
                    tmax = VERY_NEGATIVE;
                }
            }
        }

        if(tmax > tmin + LENGTH_EPS) {
            SBezier bezier = SBezier::From(p.Plus(dl.ScaledBy(tmin)),
                                           p.Plus(dl.ScaledBy(tmax)));
            AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
        }
    } else if((degm == 1 && degn == 1 && isExtdb) ||
              (b->degm == 1 && b->degn == 1 && isExtdt))
    {
        // The intersection between a plane and a surface of extrusion
        SSurface *splane, *sext;
        if(degm == 1 && degn == 1) {
            splane = this;
            sext = b;
        } else {
            splane = b;
            sext = this;
        }

        Vector n = splane->NormalAt(0, 0).WithMagnitude(1), along;
        double d = n.Dot(splane->PointAt(0, 0));
        SBezier bezier;
        (void)sext->IsExtrusion(&bezier, &along);

        if(fabs(n.Dot(along)) < LENGTH_EPS) {
            // Direction of extrusion is parallel to plane; so intersection
            // is zero or more lines. Build a line within the plane, and
            // normal to the direction of extrusion, and intersect that line
            // against the surface; each intersection point corresponds to
            // a line.
            Vector pm, alu, p0, dp;
            // a point halfway along the extrusion
            pm = ((sext->ctrl[0][0]).Plus(sext->ctrl[0][1])).ScaledBy(0.5);
            alu = along.WithMagnitude(1);
            dp = (n.Cross(along)).WithMagnitude(1);
            // n, alu, and dp form an orthogonal csys; set n component to
            // place it on the plane, alu component to lie halfway along
            // extrusion, and dp component doesn't matter so zero
            p0 = n.ScaledBy(d).Plus(alu.ScaledBy(pm.Dot(alu)));

            List<SInter> inters = {};
            sext->AllPointsIntersecting(p0, p0.Plus(dp), &inters,
                /*asSegment=*/false, /*trimmed=*/false, /*inclTangent=*/true);

            SInter *si;
            for(si = inters.First(); si; si = inters.NextAfter(si)) {
                Vector al = along.ScaledBy(0.5);
                SBezier bezier;
                bezier = SBezier::From((si->p).Minus(al), (si->p).Plus(al));
                AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
            }

            inters.Clear();
        } else {
            // Direction of extrusion is not parallel to plane; so
            // intersection is projection of extruded curve into our plane.
            int i;
            for(i = 0; i <= bezier.deg; i++) {
                Vector p0 = bezier.ctrl[i],
                       p1 = p0.Plus(along);

                bezier.ctrl[i] =
                    Vector::AtIntersectionOfPlaneAndLine(n, d, p0, p1, NULL);
            }

            AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
        }
    } else if(isExtdt && isExtdb &&
                sqrt(fabs(alongt.Dot(alongb))) >
                sqrt(alongt.Magnitude() * alongb.Magnitude()) - LENGTH_EPS)
    {
        // Two surfaces of extrusion along the same axis. So they might
        // intersect along some number of lines parallel to the axis.
        Vector axis = alongt.WithMagnitude(1);

        List<SInter> inters = {};
        List<Vector> lv = {};

        double a_axis0 = (   ctrl[0][0]).Dot(axis),
               a_axis1 = (   ctrl[0][1]).Dot(axis),
               b_axis0 = (b->ctrl[0][0]).Dot(axis),
               b_axis1 = (b->ctrl[0][1]).Dot(axis);

        if(a_axis0 > a_axis1) swap(a_axis0, a_axis1);
        if(b_axis0 > b_axis1) swap(b_axis0, b_axis1);

        double ab_axis0 = max(a_axis0, b_axis0),
               ab_axis1 = min(a_axis1, b_axis1);

        if(fabs(ab_axis0 - ab_axis1) < LENGTH_EPS) {
            // The line would be zero-length
            return;
        }

        Vector axis0 = axis.ScaledBy(ab_axis0),
               axis1 = axis.ScaledBy(ab_axis1),
               axisc = (axis0.Plus(axis1)).ScaledBy(0.5);

        oft.MakePwlInto(&lv);

        int i;
        for(i = 0; i < lv.n - 1; i++) {
            Vector pa = lv.elem[i], pb = lv.elem[i+1];
            pa = pa.Minus(axis.ScaledBy(pa.Dot(axis)));
            pb = pb.Minus(axis.ScaledBy(pb.Dot(axis)));
            pa = pa.Plus(axisc);
            pb = pb.Plus(axisc);

            b->AllPointsIntersecting(pa, pb, &inters,
                /*asSegment=*/true,/*trimmed=*/false, /*inclTangent=*/false);
        }

        SInter *si;
        for(si = inters.First(); si; si = inters.NextAfter(si)) {
            Vector p = (si->p).Minus(axis.ScaledBy((si->p).Dot(axis)));
            double ub, vb;
            b->ClosestPointTo(p, &ub, &vb, /*mustConverge=*/true);
            SSurface plane;
            plane = SSurface::FromPlane(p, axis.Normal(0), axis.Normal(1));

            b->PointOnSurfaces(this, &plane, &ub, &vb);

            p = b->PointAt(ub, vb);

            SBezier bezier;
            bezier = SBezier::From(p.Plus(axis0), p.Plus(axis1));
            AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
        }

        inters.Clear();
        lv.Clear();
    } else {
        // Try intersecting the surfaces numerically, by a marching algorithm.
        // First, we find all the intersections between a surface and the
        // boundary of the other surface.
        SPointList spl = {};
        int a;
        for(a = 0; a < 2; a++) {
            SShell   *shA  = (a == 0) ? agnstA : agnstB;
            SSurface *srfA = (a == 0) ? this : b,
                     *srfB = (a == 0) ? b : this;

            SEdgeList el = {};
            srfA->MakeEdgesInto(shA, &el, MakeAs::XYZ, NULL);

            SEdge *se;
            for(se = el.l.First(); se; se = el.l.NextAfter(se)) {
                List<SInter> lsi = {};

                srfB->AllPointsIntersecting(se->a, se->b, &lsi,
                    /*asSegment=*/true, /*trimmed=*/true, /*inclTangent=*/false);
                if(lsi.n == 0) continue;

                // Find the other surface that this curve trims.
                hSCurve hsc = { (uint32_t)se->auxA };
                SCurve *sc = shA->curve.FindById(hsc);
                hSSurface hother = (sc->surfA.v == srfA->h.v) ?
                                                    sc->surfB : sc->surfA;
                SSurface *other = shA->surface.FindById(hother);

                SInter *si;
                for(si = lsi.First(); si; si = lsi.NextAfter(si)) {
                    Vector p = si->p;
                    double u, v;
                    srfB->ClosestPointTo(p, &u, &v);
                    srfB->PointOnSurfaces(srfA, other, &u, &v);
                    p = srfB->PointAt(u, v);
                    if(!spl.ContainsPoint(p)) {
                        SPoint sp;
                        sp.p = p;
                        // We also need the edge normal, so that we know in
                        // which direction to march.
                        srfA->ClosestPointTo(p, &u, &v);
                        Vector n = srfA->NormalAt(u, v);
                        sp.auxv = n.Cross((se->b).Minus(se->a));
                        sp.auxv = (sp.auxv).WithMagnitude(1);

                        spl.l.Add(&sp);
                    }
                }
                lsi.Clear();
            }

            el.Clear();
        }

        while(spl.l.n >= 2) {
            SCurve sc = {};
            sc.surfA = h;
            sc.surfB = b->h;
            sc.isExact = false;
            sc.source = SCurve::Source::INTERSECTION;

            Vector start  = spl.l.elem[0].p,
                   startv = spl.l.elem[0].auxv;
            spl.l.ClearTags();
            spl.l.elem[0].tag = 1;
            spl.l.RemoveTagged();

            // Our chord tolerance is whatever the user specified
            double maxtol = SS.ChordTolMm();
            int maxsteps = max(300, SS.GetMaxSegments()*3);

            // The curve starts at our starting point.
            SCurvePt padd = {};
            padd.vertex = true;
            padd.p = start;
            sc.pts.Add(&padd);

            Point2d pa, pb;
            Vector np, npc = Vector::From(0, 0, 0);
            bool fwd = false;
            // Better to start with a too-small step, so that we don't miss
            // features of the curve entirely.
            double tol, step = maxtol;
            for(a = 0; a < maxsteps; a++) {
                ClosestPointTo(start, &pa);
                b->ClosestPointTo(start, &pb);

                Vector na =    NormalAt(pa).WithMagnitude(1),
                       nb = b->NormalAt(pb).WithMagnitude(1);

                if(a == 0) {
                    Vector dp = nb.Cross(na);
                    if(dp.Dot(startv) < 0) {
                        // We want to march in the more inward direction.
                        fwd = true;
                    } else {
                        fwd = false;
                    }
                }

                int i;
                for(i = 0; i < 20; i++) {
                    Vector dp = nb.Cross(na);
                    if(!fwd) dp = dp.ScaledBy(-1);
                    dp = dp.WithMagnitude(step);

                    np = start.Plus(dp);
                    npc = ClosestPointOnThisAndSurface(b, np);
                    tol = (npc.Minus(np)).Magnitude();

                    if(tol > maxtol*0.8) {
                        step *= 0.90;
                    } else {
                        step /= 0.90;
                    }

                    if((tol < maxtol) && (tol > maxtol/2)) {
                        // If we meet the chord tolerance test, and we're
                        // not too fine, then we break out.
                        break;
                    }
                }

                SPoint *sp;
                for(sp = spl.l.First(); sp; sp = spl.l.NextAfter(sp)) {
                    if((sp->p).OnLineSegment(start, npc, 2*SS.ChordTolMm())) {
                        sp->tag = 1;
                        a = maxsteps;
                        npc = sp->p;
                    }
                }

                padd.p = npc;
                padd.vertex = (a == maxsteps);
                sc.pts.Add(&padd);

                start = npc;
            }

            spl.l.RemoveTagged();

            // And now we split and insert the curve
            SCurve split = sc.MakeCopySplitAgainst(agnstA, agnstB, this, b);
            sc.Clear();
            into->curve.AddAndAssignId(&split);
        }
        spl.Clear();
    }
}
Esempio n. 13
0
void Surf::FindBorderCurves()
{
	double degen_tol = 0.000001;

	//==== Load 4 Border Curves if Not Degenerate ====//
	SCurve* scrv;
	double max_u = (m_NumU-1)/3.0;
	double max_w = (m_NumW-1)/3.0;

	vector< vec3d > pnts;
	pnts.resize( 4 );

	pnts[0].set_xyz( 0,		    0, 0 );			// Inc U
	pnts[1].set_xyz( max_u/2,   0, 0 );
	pnts[2].set_xyz( max_u/2, 0, 0 );
	pnts[3].set_xyz( max_u,     0, 0 );

	scrv = new SCurve( this );
	scrv->SetBezierControlPnts( pnts );

	if ( scrv->Length(10) > degen_tol )
		m_SCurveVec.push_back( scrv );
	else
		delete scrv;

	pnts[0].set_xyz( max_u,		  0, 0 );		// Inc W
	pnts[1].set_xyz( max_u,   max_w/2, 0 );
	pnts[2].set_xyz( max_u,   max_w/2, 0 );
	pnts[3].set_xyz( max_u,     max_w, 0 );

	scrv = new SCurve( this );
	scrv->SetBezierControlPnts( pnts );

	if ( scrv->Length(10) > degen_tol )
		m_SCurveVec.push_back( scrv );
	else
		delete scrv;

	pnts[0].set_xyz( max_u,	    max_w, 0 );			// Dec U
	pnts[1].set_xyz( max_u/2,	max_w, 0 );
	pnts[2].set_xyz( max_u/2,	max_w, 0 );
	pnts[3].set_xyz( 0,	        max_w, 0 );

	scrv = new SCurve( this );
	scrv->SetBezierControlPnts( pnts );

	if ( scrv->Length(10) > degen_tol )
		m_SCurveVec.push_back( scrv );
	else
		delete scrv;

	pnts[0].set_xyz( 0,	max_w,   0 );			// Dec W
	pnts[1].set_xyz( 0,	max_w/2, 0 );
	pnts[2].set_xyz( 0,	max_w/2, 0 );
	pnts[3].set_xyz( 0,	0,       0 );

	scrv = new SCurve( this );
	scrv->SetBezierControlPnts( pnts );

	if ( scrv->Length(10) > degen_tol )
		m_SCurveVec.push_back( scrv );
	else
		delete scrv;
}