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