Example #1
0
Vector Vector::AtIntersectionOfLines(Vector a0, Vector a1,
                                     Vector b0, Vector b1,
                                     bool *skew,
                                     double *parama, double *paramb)
{
    Vector da = a1.Minus(a0), db = b1.Minus(b0);

    double pa, pb;
    Vector::ClosestPointBetweenLines(a0, da, b0, db, &pa, &pb);

    if(parama) *parama = pa;
    if(paramb) *paramb = pb;

    // And from either of those, we get the intersection point.
    Vector pi = a0.Plus(da.ScaledBy(pa));

    if(skew) {
        // Check if the intersection points on each line are actually
        // coincident...
        if(pi.Equals(b0.Plus(db.ScaledBy(pb)))) {
            *skew = false;
        } else {
            *skew = true;
        }
    }
    return pi;
}
Example #2
0
void Constraint::DoEqualLenTicks(Vector a, Vector b, Vector gn) {
    Vector m = (a.ScaledBy(1.0/3)).Plus(b.ScaledBy(2.0/3));
    Vector ab = a.Minus(b);
    Vector n = (gn.Cross(ab)).WithMagnitude(10/SS.GW.scale);

    LineDrawOrGetDistance(m.Minus(n), m.Plus(n));
}
Example #3
0
void SBezier::ClosestPointTo(Vector p, double *t, bool converge) {
    int i;
    double minDist = VERY_POSITIVE;
    *t = 0;
    double res = (deg <= 2) ? 7.0 : 20.0;
    for(i = 0; i < (int)res; i++) {
        double tryt = (i/res);
        
        Vector tryp = PointAt(tryt);
        double d = (tryp.Minus(p)).Magnitude();
        if(d < minDist) {
            *t = tryt;
            minDist = d;
        }
    }

    Vector p0;
    for(i = 0; i < (converge ? 15 : 5); i++) {
        p0 = PointAt(*t);
        if(p0.Equals(p, RATPOLY_EPS)) {
            return;
        }

        Vector dp = TangentAt(*t);
        Vector pc = p.ClosestPointOnLine(p0, dp);
        *t += (pc.Minus(p0)).DivPivoting(dp);
    }
    if(converge) {
        dbp("didn't converge (closest point on bezier curve)");
    }
}
Example #4
0
bool SSurface::ClosestPointNewton(Vector p, double *u, double *v, bool converge)
{
    // Initial guess is in u, v; refine by Newton iteration.
    Vector p0 = Vector::From(0, 0, 0);
    for(int i = 0; i < (converge ? 25 : 5); i++) {
        p0 = PointAt(*u, *v);
        if(converge) {
            if(p0.Equals(p, RATPOLY_EPS)) {
                return true;
            }
        }

        Vector tu, tv;
        TangentsAt(*u, *v, &tu, &tv);
        
        // Project the point into a plane through p0, with basis tu, tv; a
        // second-order thing would converge faster but needs second
        // derivatives.
        Vector dp = p.Minus(p0);
        double du = dp.Dot(tu), dv = dp.Dot(tv);
        *u += du / (tu.MagSquared());
        *v += dv / (tv.MagSquared());
    }

    if(converge) {
        dbp("didn't converge");
        dbp("have %.3f %.3f %.3f", CO(p0));
        dbp("want %.3f %.3f %.3f", CO(p));
        dbp("distance = %g", (p.Minus(p0)).Magnitude());
    }
    return false;
}
Example #5
0
void ssglFatLine(Vector a, Vector b, double width)
{
    // The half-width of the line we're drawing.
    double hw = width / 2;
    Vector ab  = b.Minus(a);
    Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
    Vector abn = (ab.Cross(gn)).WithMagnitude(1);
    abn = abn.Minus(gn.ScaledBy(gn.Dot(abn)));
    // So now abn is normal to the projection of ab into the screen, so the
    // line will always have constant thickness as the view is rotated.

    abn = abn.WithMagnitude(hw);
    ab  = gn.Cross(abn);
    ab  = ab. WithMagnitude(hw);

    // The body of a line is a quad
    glBegin(GL_QUADS);
    ssglVertex3v(a.Minus(abn));
    ssglVertex3v(b.Minus(abn));
    ssglVertex3v(b.Plus (abn));
    ssglVertex3v(a.Plus (abn));
    glEnd();
    // And the line has two semi-circular end caps.
    FatLineEndcap(a, ab,              abn);
    FatLineEndcap(b, ab.ScaledBy(-1), abn);
}
Example #6
0
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;
    }
}
Example #7
0
void GraphicsWindow::Selection::Draw(void) {
    Vector refp = Vector::From(0, 0, 0);
    if(entity.v) {
        Entity *e = SK.GetEntity(entity);
        e->Draw();
        if(emphasized) refp = e->GetReferencePos();
    }
    if(constraint.v) {
        Constraint *c = SK.GetConstraint(constraint);
        c->Draw();
        if(emphasized) refp = c->GetReferencePos();
    }
    if(emphasized && (constraint.v || entity.v)) {
        // We want to emphasize this constraint or entity, by drawing a thick
        // line from the top left corner of the screen to the reference point
        // of that entity or constraint.
        double s = 0.501/SS.GW.scale;
        Vector topLeft =       SS.GW.projRight.ScaledBy(-SS.GW.width*s);
        topLeft = topLeft.Plus(SS.GW.projUp.ScaledBy(SS.GW.height*s));
        topLeft = topLeft.Minus(SS.GW.offset);

        glLineWidth(40);
        RgbColor rgb = Style::Color(Style::HOVERED);
        glColor4d(rgb.redF(), rgb.greenF(), rgb.blueF(), 0.2);
        glBegin(GL_LINES);
            ssglVertex3v(topLeft);
            ssglVertex3v(refp);
        glEnd();
        glLineWidth(1);
    }
}
Example #8
0
void SBezier::MakePwlWorker(List<Vector> *l, double ta, double tb,
                                double chordTol)
{
    Vector pa = PointAt(ta);
    Vector pb = PointAt(tb);

    // Can't test in the middle, or certain cubics would break.
    double tm1 = (2*ta + tb) / 3;
    double tm2 = (ta + 2*tb) / 3;

    Vector pm1 = PointAt(tm1);
    Vector pm2 = PointAt(tm2);

    double d = max(pm1.DistanceToLine(pa, pb.Minus(pa)),
                   pm2.DistanceToLine(pa, pb.Minus(pa)));

    double step = 1.0/SS.maxSegments;
    if((tb - ta) < step || d < chordTol) {
        // A previous call has already added the beginning of our interval.
        l->Add(&pb);
    } else {
        double tm = (ta + tb) / 2;
        MakePwlWorker(l, ta, tm, chordTol);
        MakePwlWorker(l, tm, tb, chordTol);
    }
}
Example #9
0
//-----------------------------------------------------------------------------
// A curve by its parametric equation, helper functions for computing tangent
// arcs by a numerical method.
//-----------------------------------------------------------------------------
void GraphicsWindow::ParametricCurve::MakeFromEntity(hEntity he, bool reverse) {
    ZERO(this);
    Entity *e = SK.GetEntity(he);
    if(e->type == Entity::LINE_SEGMENT) {
        isLine = true;
        p0 = e->EndpointStart(),
        p1 = e->EndpointFinish();
        if(reverse) {
            SWAP(Vector, p0, p1);
        }
    } else if(e->type == Entity::ARC_OF_CIRCLE) {
        isLine = false;
        p0 = SK.GetEntity(e->point[0])->PointGetNum();
        Vector pe = SK.GetEntity(e->point[1])->PointGetNum();
        r = (pe.Minus(p0)).Magnitude();
        e->ArcGetAngles(&theta0, &theta1, &dtheta);
        if(reverse) {
            SWAP(double, theta0, theta1);
            dtheta = -dtheta;
        }
        EntityBase *wrkpln = SK.GetEntity(e->workplane)->Normal();
        u = wrkpln->NormalU();
        v = wrkpln->NormalV();
    } else {
        oops();
    }
}
Example #10
0
bool Vector::BoundingBoxIntersectsLine(Vector amax, Vector amin,
                                       Vector p0, Vector p1, bool segment)
{
    Vector dp = p1.Minus(p0);
    double lp = dp.Magnitude();
    dp = dp.ScaledBy(1.0/lp);

    int i, a;
    for(i = 0; i < 3; i++) {
        int j = WRAP(i+1, 3), k = WRAP(i+2, 3);
        if(lp*fabs(dp.Element(i)) < LENGTH_EPS) continue; // parallel to plane

        for(a = 0; a < 2; a++) {
            double d = (a == 0) ? amax.Element(i) : amin.Element(i);
            // n dot (p0 + t*dp) = d
            // (n dot p0) + t * (n dot dp) = d
            double t = (d - p0.Element(i)) / dp.Element(i);
            Vector p = p0.Plus(dp.ScaledBy(t));

            if(segment && (t < -LENGTH_EPS || t > (lp+LENGTH_EPS))) continue;

            if(p.Element(j) > amax.Element(j) + LENGTH_EPS) continue;
            if(p.Element(k) > amax.Element(k) + LENGTH_EPS) continue;

            if(p.Element(j) < amin.Element(j) - LENGTH_EPS) continue;
            if(p.Element(k) < amin.Element(k) - LENGTH_EPS) continue;

            return true;
        }
    }

    return false;
}
Example #11
0
double EntityBase::CircleGetRadiusNum(void) {
    if(type == CIRCLE) {
        return SK.GetEntity(distance)->DistanceGetNum();
    } else if(type == ARC_OF_CIRCLE) {
        Vector c  = SK.GetEntity(point[0])->PointGetNum();
        Vector pa = SK.GetEntity(point[1])->PointGetNum();
        return (pa.Minus(c)).Magnitude();
    } else oops();
}
Example #12
0
//-----------------------------------------------------------------------------
// Draw a line with arrows on both ends, and possibly a gap in the middle for
// the dimension. We will use these for most length dimensions. The length
// being dimensioned is from A to B; but those points get extended perpendicular
// to the line AB, until the line between the extensions crosses ref (the
// center of the label).
//-----------------------------------------------------------------------------
void Constraint::DoLineWithArrows(Vector ref, Vector a, Vector b,
                                  bool onlyOneExt)
{
    Vector gn = (SS.GW.projRight.Cross(SS.GW.projUp)).WithMagnitude(1);
    double pixels = 1.0 / SS.GW.scale;

    Vector ab   = a.Minus(b);
    Vector ar   = a.Minus(ref);
    // Normal to a plane containing the line and the label origin.
    Vector n    = ab.Cross(ar);
    // Within that plane, and normal to the line AB; so that's our extension
    // line.
    Vector out  = ab.Cross(n).WithMagnitude(1);
    out = out.ScaledBy(-out.Dot(ar));

    Vector ae = a.Plus(out), be = b.Plus(out);

    // Extension lines extend 10 pixels beyond where the arrows get
    // drawn (which is at the same offset perpendicular from AB as the
    // label).
    LineDrawOrGetDistance(a, ae.Plus(out.WithMagnitude(10*pixels)));
    if(!onlyOneExt) {
        LineDrawOrGetDistance(b, be.Plus(out.WithMagnitude(10*pixels)));
    }

    int within = DoLineTrimmedAgainstBox(ref, ae, be);

    // Arrow heads are 13 pixels long, with an 18 degree half-angle.
    double theta = 18*PI/180;
    Vector arrow = (be.Minus(ae)).WithMagnitude(13*pixels);

    if(within != 0) {
        arrow = arrow.ScaledBy(-1);
        Vector seg = (be.Minus(ae)).WithMagnitude(18*pixels);
        if(within < 0) LineDrawOrGetDistance(ae, ae.Minus(seg));
        if(within > 0) LineDrawOrGetDistance(be, be.Plus(seg));
    }

    LineDrawOrGetDistance(ae, ae.Plus(arrow.RotatedAbout(n,  theta)));
    LineDrawOrGetDistance(ae, ae.Plus(arrow.RotatedAbout(n, -theta)));
    arrow = arrow.ScaledBy(-1);
    LineDrawOrGetDistance(be, be.Plus(arrow.RotatedAbout(n,  theta)));
    LineDrawOrGetDistance(be, be.Plus(arrow.RotatedAbout(n, -theta)));
}
Example #13
0
Vector Vector::ClosestPointOnLine(Vector p0, Vector dp) {
    dp = dp.WithMagnitude(1);
    // this, p0, and (p0+dp) define a plane; the min distance is in
    // that plane, so calculate its normal
    Vector pn = (this->Minus(p0)).Cross(dp);
    // The minimum distance line is in that plane, perpendicular
    // to the line
    Vector n = pn.Cross(dp);

    // Calculate the actual distance
    double d = (dp.Cross(p0.Minus(*this))).Magnitude();
    return this->Plus(n.WithMagnitude(d));
}
Example #14
0
//-----------------------------------------------------------------------------
// If a color is almost white, then we can rewrite it to black, just so that
// it won't disappear on file formats with a light background.
//-----------------------------------------------------------------------------
RgbColor Style::RewriteColor(RgbColor rgbin) {
    Vector rgb = Vector::From(rgbin.redF(), rgbin.greenF(), rgbin.blueF());
    rgb = rgb.Minus(Vector::From(1, 1, 1));
    if(rgb.Magnitude() < 0.4 && SS.fixExportColors) {
        // This is an almost-white color in a default style, which is
        // good for the default on-screen view (black bg) but probably
        // not desired in the exported files, which typically are shown
        // against white backgrounds.
        return RGBi(0, 0, 0);
    } else {
        return rgbin;
    }
}
Example #15
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);
}
Example #16
0
SSurface SSurface::FromRevolutionOf(SBezier *sb, Vector pt, Vector axis,
                                    double thetas, double thetaf)
{
    SSurface ret = {};


    ret.degm = sb->deg;
    ret.degn = 2;

    double dtheta = fabs(WRAP_SYMMETRIC(thetaf - thetas, 2*PI));

    // We now wish to revolve the curve about the z axis
    int i;
    for(i = 0; i <= ret.degm; i++) {
        Vector p = sb->ctrl[i];

        Vector ps = p.RotatedAbout(pt, axis, thetas),
               pf = p.RotatedAbout(pt, axis, thetaf);

        Vector ct;
        if(ps.Equals(pf)) {
            // Degenerate case: a control point lies on the axis of revolution,
            // so we get three coincident control points.
            ct = ps;
        } else {
            // Normal case, the control point sweeps out a circle.
            Vector c = ps.ClosestPointOnLine(pt, axis);

            Vector rs = ps.Minus(c),
                   rf = pf.Minus(c);

            Vector ts = axis.Cross(rs),
                   tf = axis.Cross(rf);

            ct = Vector::AtIntersectionOfLines(ps, ps.Plus(ts),
                                               pf, pf.Plus(tf),
                                               NULL, NULL, NULL);
        }

        ret.ctrl[i][0] = ps;
        ret.ctrl[i][1] = ct;
        ret.ctrl[i][2] = pf;

        ret.weight[i][0] = sb->weight[i];
        ret.weight[i][1] = sb->weight[i]*cos(dtheta/2);
        ret.weight[i][2] = sb->weight[i];
    }

    return ret;
}
double SSurface::ChordToleranceForEdge(Vector a, Vector b) {
    Vector as = PointAt(a.x, a.y), bs = PointAt(b.x, b.y);

    double worst = VERY_NEGATIVE;
    int i;
    for(i = 1; i <= 3; i++) {
        Vector p  = a. Plus((b. Minus(a )).ScaledBy(i/4.0)),
               ps = as.Plus((bs.Minus(as)).ScaledBy(i/4.0));

        Vector pps = PointAt(p.x, p.y);
        worst = max(worst, (pps.Minus(ps)).MagSquared());
    }
    return sqrt(worst);
}
Example #18
0
void Group::GenerateForStepAndRepeat(T *steps, T *outs) {
    T workA, workB;
    workA = {};
    workB = {};
    T *soFar = &workA, *scratch = &workB;

    int n = (int)valA, a0 = 0;
    if(subtype == ONE_SIDED && skipFirst) {
        a0++; n++;
    }
    int a;
    for(a = a0; a < n; a++) {
        int ap = a*2 - (subtype == ONE_SIDED ? 0 : (n-1));
        int remap = (a == (n - 1)) ? REMAP_LAST : a;

        T transd = {};
        if(type == TRANSLATE) {
            Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
            trans = trans.ScaledBy(ap);
            transd.MakeFromTransformationOf(steps,
                trans, Quaternion::IDENTITY, 1.0);
        } else {
            Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
            double theta = ap * SK.GetParam(h.param(3))->val;
            double c = cos(theta), s = sin(theta);
            Vector axis = Vector::From(h.param(4), h.param(5), h.param(6));
            Quaternion q = Quaternion::From(c, s*axis.x, s*axis.y, s*axis.z);
            // Rotation is centered at t; so A(x - t) + t = Ax + (t - At)
            transd.MakeFromTransformationOf(steps,
                trans.Minus(q.Rotate(trans)), q, 1.0);
        }

        // We need to rewrite any plane face entities to the transformed ones.
        transd.RemapFaces(this, remap);

        // And tack this transformed copy on to the return.
        if(soFar->IsEmpty()) {
            scratch->MakeFromCopyOf(&transd);
        } else {
            scratch->MakeFromUnionOf(soFar, &transd);
        }

        swap(scratch, soFar);
        scratch->Clear();
        transd.Clear();
    }

    outs->Clear();
    *outs = *soFar;
}
Example #19
0
bool Vector::OnLineSegment(Vector a, Vector b, double tol) {
    if(this->Equals(a, tol) || this->Equals(b, tol)) return true;

    Vector d = b.Minus(a);

    double m = d.MagSquared();
    double distsq = ((this->Minus(a)).Cross(d)).MagSquared() / m;

    if(distsq >= tol*tol) return false;

    double t = (this->Minus(a)).DivPivoting(d);
    // On-endpoint already tested
    if(t < 0 || t > 1) return false;
    return true;
}
Example #20
0
void SSurface::PointOnSurfaces(SSurface *s1, SSurface *s2,
                                                double *up, double *vp)
{
    double u[3] = { *up, 0, 0 }, v[3] = { *vp, 0, 0 };
    SSurface *srf[3] = { this, s1, s2 };

    // Get initial guesses for (u, v) in the other surfaces
    Vector p = PointAt(*u, *v);
    (srf[1])->ClosestPointTo(p, &(u[1]), &(v[1]), false);
    (srf[2])->ClosestPointTo(p, &(u[2]), &(v[2]), false);

    int i, j;
    for(i = 0; i < 20; i++) {
        // Approximate each surface by a plane
        Vector p[3], tu[3], tv[3], n[3];
        double d[3];
        for(j = 0; j < 3; j++) {
            p[j] = (srf[j])->PointAt(u[j], v[j]);
            (srf[j])->TangentsAt(u[j], v[j], &(tu[j]), &(tv[j]));
            n[j] = ((tu[j]).Cross(tv[j])).WithMagnitude(1);
            d[j] = (n[j]).Dot(p[j]);
        }

        // If a = b and b = c, then does a = c? No, it doesn't.
        if((p[0]).Equals(p[1], RATPOLY_EPS) && 
           (p[1]).Equals(p[2], RATPOLY_EPS) &&
           (p[2]).Equals(p[0], RATPOLY_EPS))
        {
            *up = u[0];
            *vp = v[0];
            return;
        }

        bool parallel;
        Vector pi = Vector::AtIntersectionOfPlanes(n[0], d[0],
                                                   n[1], d[1],
                                                   n[2], d[2], &parallel);
        if(parallel) break;

        for(j = 0; j < 3; j++) {
            Vector dp = pi.Minus(p[j]);
            double du = dp.Dot(tu[j]), dv = dp.Dot(tv[j]);
            u[j] += du / (tu[j]).MagSquared();
            v[j] += dv / (tv[j]).MagSquared();
        }
    }
    dbp("didn't converge (three surfaces intersecting)");
}
Example #21
0
Vector SSurface::ClosestPointOnThisAndSurface(SSurface *srf2, Vector p) {
    // This is untested.
    int i, j;
    Point2d puv[2];
    SSurface *srf[2] = { this, srf2 };

    for(j = 0; j < 2; j++) {
        (srf[j])->ClosestPointTo(p, &(puv[j]), false);
    }

    for(i = 0; i < 10; i++) {
        Vector tu[2], tv[2], cp[2], n[2];
        double d[2];

        for(j = 0; j < 2; j++) {
            (srf[j])->TangentsAt(puv[j].x, puv[j].y, &(tu[j]), &(tv[j]));

            cp[j] = (srf[j])->PointAt(puv[j]);

            n[j] = ((tu[j]).Cross(tv[j])).WithMagnitude(1);
            d[j] = (n[j]).Dot(cp[j]);
        }

        if((cp[0]).Equals(cp[1], RATPOLY_EPS)) break;

        Vector p0 = Vector::AtIntersectionOfPlanes(n[0], d[0], n[1], d[1]),
               dp = (n[0]).Cross(n[1]);
        
        Vector pc = p.ClosestPointOnLine(p0, dp);

        // Adjust our guess and iterate
        for(j = 0; j < 2; j++) {
            Vector dc = pc.Minus(cp[j]);
            double du = dc.Dot(tu[j]), dv = dc.Dot(tv[j]);
            puv[j].x += du / ((tu[j]).MagSquared());
            puv[j].y += dv / ((tv[j]).MagSquared());
        }
    }
    if(i >= 10) {
        dbp("this and srf, didn't converge, d=%g",
            (puv[0].Minus(puv[1])).Magnitude());
    }

    // If this converged, then the two points are actually equal.
    return ((srf[0])->PointAt(puv[0])).Plus(
           ((srf[1])->PointAt(puv[1]))).ScaledBy(0.5);
}
Example #22
0
Vector GraphicsWindow::SnapToGrid(Vector p) {
    if(!LockedInWorkplane()) return p;

    EntityBase *wrkpl = SK.GetEntity(ActiveWorkplane()),
               *norm  = wrkpl->Normal();
    Vector wo = SK.GetEntity(wrkpl->point[0])->PointGetNum(),
           wu = norm->NormalU(),
           wv = norm->NormalV(),
           wn = norm->NormalN();

    Vector pp = (p.Minus(wo)).DotInToCsys(wu, wv, wn);
    pp.x = floor((pp.x / SS.gridSpacing) + 0.5)*SS.gridSpacing;
    pp.y = floor((pp.y / SS.gridSpacing) + 0.5)*SS.gridSpacing;
    pp.z = 0;

    return pp.ScaleOutOfCsys(wu, wv, wn).Plus(wo);
}
Example #23
0
void SEdgeList::MergeCollinearSegments(Vector a, Vector b) {
    LineStart = a;
    LineDirection = b.Minus(a);
    qsort(l.elem, l.n, sizeof(l.elem[0]), ByTAlongLine);

    l.ClearTags();
    int i;
    for(i = 1; i < l.n; i++) {
        SEdge *prev = &(l.elem[i-1]),
              *now  = &(l.elem[i]);

        if((prev->b).Equals(now->a)) {
            // The previous segment joins up to us; so merge it into us.
            prev->tag = 1;
            now->a = prev->a;
        }
    }
    l.RemoveTagged();
}
Example #24
0
Vector Vector::AtIntersectionOfPlaneAndLine(Vector n, double d,
                                            Vector p0, Vector p1,
                                            bool *parallel)
{
    Vector dp = p1.Minus(p0);

    if(fabs(n.Dot(dp)) < LENGTH_EPS) {
        if(parallel) *parallel = true;
        return Vector::From(0, 0, 0);
    }

    if(parallel) *parallel = false;

    // n dot (p0 + t*dp) = d
    // (n dot p0) + t * (n dot dp) = d
    double t = (d - n.Dot(p0)) / (n.Dot(dp));

    return p0.Plus(dp.ScaledBy(t));
}
Example #25
0
void Vector::ClosestPointBetweenLines(Vector a0, Vector da,
                                      Vector b0, Vector db,
                                      double *ta, double *tb)
{
    Vector a1 = a0.Plus(da),
           b1 = a1.Plus(db);

    // Make a semi-orthogonal coordinate system from those directions;
    // note that dna and dnb need not be perpendicular.
    Vector dn = da.Cross(db); // normal to both
    Vector dna = dn.Cross(da); // normal to da
    Vector dnb = dn.Cross(db); // normal to db

    // At the intersection of the lines
    //    a0 + pa*da = b0 + pb*db (where pa, pb are scalar params)
    // So dot this equation against dna and dnb to get two equations
    // to solve for da and db
    *tb =  ((a0.Minus(b0)).Dot(dna))/(db.Dot(dna));
    *ta = -((a0.Minus(b0)).Dot(dnb))/(da.Dot(dnb));   
}
Example #26
0
void Constraint::DoEqualRadiusTicks(hEntity he) {
    Entity *circ = SK.GetEntity(he);

    Vector center = SK.GetEntity(circ->point[0])->PointGetNum();
    double r = circ->CircleGetRadiusNum();
    Quaternion q = circ->Normal()->NormalGetNum();
    Vector u = q.RotationU(), v = q.RotationV();

    double theta;
    if(circ->type == Entity::CIRCLE) {
        theta = PI/2;
    } else if(circ->type == Entity::ARC_OF_CIRCLE) {
        double thetaa, thetab, dtheta;
        circ->ArcGetAngles(&thetaa, &thetab, &dtheta);
        theta = thetaa + dtheta/2;
    } else oops();

    Vector d = u.ScaledBy(cos(theta)).Plus(v.ScaledBy(sin(theta)));
    d = d.ScaledBy(r);
    Vector p = center.Plus(d);
    Vector tick = d.WithMagnitude(10/SS.GW.scale);
    LineDrawOrGetDistance(p.Plus(tick), p.Minus(tick));
}
Example #27
0
void Group::MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in) {
    Entity *ep = SK.GetEntity(in);

    Entity en;
    ZERO(&en);
    if(ep->IsPoint()) {
        // A point gets extruded to form a line segment
        en.point[0] = Remap(ep->h, REMAP_TOP);
        en.point[1] = Remap(ep->h, REMAP_BOTTOM);
        en.group = h;
        en.construction = ep->construction;
        en.style = ep->style;
        en.h = Remap(ep->h, REMAP_PT_TO_LINE);
        en.type = Entity::LINE_SEGMENT;
        el->Add(&en);
    } else if(ep->type == Entity::LINE_SEGMENT) {
        // A line gets extruded to form a plane face; an endpoint of the
        // original line is a point in the plane, and the line is in the plane.
        Vector a = SK.GetEntity(ep->point[0])->PointGetNum();
        Vector b = SK.GetEntity(ep->point[1])->PointGetNum();
        Vector ab = b.Minus(a);

        en.param[0] = h.param(0);
        en.param[1] = h.param(1);
        en.param[2] = h.param(2);
        en.numPoint = a;
        en.numNormal = Quaternion::From(0, ab.x, ab.y, ab.z);

        en.group = h;
        en.construction = ep->construction;
        en.style = ep->style;
        en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
        en.type = Entity::FACE_XPROD;
        el->Add(&en);
    }
}
Example #28
0
int _tmain(int argc, _TCHAR* argv[])
{
	setlocale(LC_CTYPE, "RUSSIAN");
	Vector a;
	a.Add_size();
	a.Massive();
	a.Sum();
	a.Element();
	Vector b = Vector(a);
	a.Plus();
	b.Minus();
	cout << endl;
	Vector mass[5];
	for (int i = 0; i < 5; i++)
	{
		mass[i].Add_size();
		mass[i].Massive();
	}
	cout << "„етные элементы: " << endl;
	for (int i = 0; i < 5; i++)
	{
		if (mass[i].mod() == 1) mass[i].print();
	}
	int maxS = mass[0].Sum(), maxS_n = 0;
	for (int i = 1; i < 5; i++)
	{ 
		if(mass[i].Sum()>maxS)
		{ 
			maxS = mass[i].Sum();
			maxS_n = i;
		}
	}
	cout << "—ама¤ больша¤ сумма: " << mass[maxS_n].Sum()<<endl;
	system("pause");
	return 0;
}
Example #29
0
void EntityBase::PointForceTo(Vector p) {
    switch(type) {
        case POINT_IN_3D:
            SK.GetParam(param[0])->val = p.x;
            SK.GetParam(param[1])->val = p.y;
            SK.GetParam(param[2])->val = p.z;
            break;

        case POINT_IN_2D: {
            EntityBase *c = SK.GetEntity(workplane);
            p = p.Minus(c->WorkplaneGetOffset());
            SK.GetParam(param[0])->val = p.Dot(c->Normal()->NormalU());
            SK.GetParam(param[1])->val = p.Dot(c->Normal()->NormalV());
            break;
        }

        case POINT_N_TRANS: {
            if(timesApplied == 0) break;
            Vector trans = (p.Minus(numPoint)).ScaledBy(1.0/timesApplied);
            SK.GetParam(param[0])->val = trans.x;
            SK.GetParam(param[1])->val = trans.y;
            SK.GetParam(param[2])->val = trans.z;
            break;
        }

        case POINT_N_ROT_TRANS: {
            // Force only the translation; leave the rotation unchanged. But
            // remember that we're working with respect to the rotated
            // point.
            Vector trans = p.Minus(PointGetQuaternion().Rotate(numPoint));
            SK.GetParam(param[0])->val = trans.x;
            SK.GetParam(param[1])->val = trans.y;
            SK.GetParam(param[2])->val = trans.z;
            break;
        }

        case POINT_N_ROT_AA: {
            // Force only the angle; the axis and center of rotation stay
            Vector offset = Vector::From(param[0], param[1], param[2]);
            Vector normal = Vector::From(param[4], param[5], param[6]);
            Vector u = normal.Normal(0), v = normal.Normal(1);
            Vector po = p.Minus(offset), numo = numPoint.Minus(offset);
            double thetap = atan2(v.Dot(po), u.Dot(po));
            double thetan = atan2(v.Dot(numo), u.Dot(numo));
            double thetaf = (thetap - thetan);
            double thetai = (SK.GetParam(param[3])->val)*timesApplied*2;
            double dtheta = thetaf - thetai;
            // Take the smallest possible change in the actual step angle,
            // in order to avoid jumps when you cross from +pi to -pi
            while(dtheta < -PI) dtheta += 2*PI;
            while(dtheta > PI) dtheta -= 2*PI;
            SK.GetParam(param[3])->val = (thetai + dtheta)/(timesApplied*2);
            break;
        }

        case POINT_N_COPY:
            // Nothing to do; it's a static copy
            break;

        default: oops();
    }
}
Example #30
0
Vector EntityBase::CubicGetFinishTangentNum(void) {
    Vector pon  = SK.GetEntity(point[3+extraPoints])->PointGetNum(),
           poff = SK.GetEntity(point[2+extraPoints])->PointGetNum();
    return (pon.Minus(poff));
}