Пример #1
0
//-----------------------------------------------------------------------------
// If our list contains multiple identical Beziers (in either forward or
// reverse order), then cull them.
//-----------------------------------------------------------------------------
void SBezierList::CullIdenticalBeziers(void) {
    int i, j;

    l.ClearTags();
    for(i = 0; i < l.n; i++) {
        SBezier *bi = &(l.elem[i]), bir;
        bir = *bi;
        bir.Reverse();

        for(j = i + 1; j < l.n; j++) {
            SBezier *bj = &(l.elem[j]);
            if(bj->Equals(bi) ||
               bj->Equals(&bir))
            {
                bi->tag = 1;
                bj->tag = 1;
            }
        }
    }
    l.RemoveTagged();
}
Пример #2
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);
}