void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
    if(dogd.drawing) {
        // Draw comments in the specified style, but everything else in the
        // default style for constraints.
        hStyle hs;
        if(type == COMMENT && disp.style.v) {
            hs = disp.style;
        } else {
            hs.v = Style::CONSTRAINT;
        }

        if(dogd.sel) {
            dogd.sel->AddEdge(a, b, hs.v);
        } else {
            // The only constraints with styles should be comments, so don't
            // check otherwise, save looking up the styles constantly.
            if(type == COMMENT && Style::Width(hs) >= 3.0) {
                ssglFatLine(a, b, Style::Width(hs) / SS.GW.scale);
            } else {
                glBegin(GL_LINE_STRIP);
                    ssglVertex3v(a);
                    ssglVertex3v(b);
                glEnd();
            }
        }
    } else {
        Point2d ap = SS.GW.ProjectPoint(a);
        Point2d bp = SS.GW.ProjectPoint(b);

        double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true);
        dogd.dmin = min(dogd.dmin, d);
    }
    dogd.refp = (a.Plus(b)).ScaledBy(0.5);
}
Beispiel #2
0
void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) {
    if(dogd.drawing) {
        // Draw lines from active group in front of those from previous
        ssglDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 3);
        // Narrow lines are drawn as lines, but fat lines must be drawn as
        // filled polygons, to get the line join style right.
        if(!maybeFat || dogd.lineWidth < 3) {
            glBegin(GL_LINES);
                ssglVertex3v(a);
                ssglVertex3v(b);
            glEnd();
        } else {
            ssglFatLine(a, b, dogd.lineWidth/SS.GW.scale);
        }

        ssglDepthRangeOffset(0);
    } else {
        Point2d ap = SS.GW.ProjectPoint(a);
        Point2d bp = SS.GW.ProjectPoint(b);

        double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true);
        // A little bit easier to select in the active group
        if(group.v == SS.GW.activeGroup.v) d -= 1;
        dogd.dmin = min(dogd.dmin, d);
    }
    dogd.refp = (a.Plus(b)).ScaledBy(0.5);
}
void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
    double th;
    if(type == COMMENT) {
        th = Style::TextHeight(disp.style);
    } else {
        th = DEFAULT_TEXT_HEIGHT;
    }

    char *s = Label();
    double swidth  = ssglStrWidth(s, th),
           sheight = ssglStrHeight(th);

    // By default, the reference is from the center; but the style could
    // specify otherwise if one is present, and it could also specify a
    // rotation.
    if(type == COMMENT && disp.style.v) {
        Style *st = Style::Get(disp.style);
        // rotation first
        double rads = st->textAngle*PI/180;
        double c = cos(rads), s = sin(rads);
        Vector pr = gr, pu = gu;
        gr = pr.ScaledBy( c).Plus(pu.ScaledBy(s));
        gu = pr.ScaledBy(-s).Plus(pu.ScaledBy(c));
        // then origin
        int o = st->textOrigin;
        if(o & Style::ORIGIN_LEFT) ref = ref.Plus(gr.WithMagnitude(swidth/2));
        if(o & Style::ORIGIN_RIGHT) ref = ref.Minus(gr.WithMagnitude(swidth/2));
        if(o & Style::ORIGIN_BOT) ref = ref.Plus(gu.WithMagnitude(sheight/2));
        if(o & Style::ORIGIN_TOP) ref = ref.Minus(gu.WithMagnitude(sheight/2));
    }

    if(labelPos) {
        // labelPos is from the top left corner (for the text box used to
        // edit things), but ref is from the center.
        *labelPos = ref.Minus(gr.WithMagnitude(swidth/2)).Minus(
                              gu.WithMagnitude(sheight/2));
    }


    if(dogd.drawing) {
        ssglWriteTextRefCenter(s, th, ref, gr, gu, LineCallback, this);
    } else {
        double l = swidth/2 - sheight/2;
        l = max(l, 5/SS.GW.scale);
        Point2d a = SS.GW.ProjectPoint(ref.Minus(gr.WithMagnitude(l)));
        Point2d b = SS.GW.ProjectPoint(ref.Plus (gr.WithMagnitude(l)));
        double d = dogd.mp.DistanceToLine(a, b.Minus(a), true);

        dogd.dmin = min(dogd.dmin, d - (th / 2));
        dogd.refp = ref;
    }
}
Beispiel #4
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);
}