Пример #1
0
void SPolygon::UvGridTriangulateInto(SMesh *mesh, SSurface *srf) {
    SEdgeList orig;
    ZERO(&orig);
    MakeEdgesInto(&orig);

    SEdgeList holes;
    ZERO(&holes);

    normal = Vector::From(0, 0, 1);
    FixContourDirections();

    // Build a rectangular grid, with horizontal and vertical lines in the
    // uv plane. The spacing of these lines is adaptive, so calculate that.
    List<double> li, lj;
    ZERO(&li);
    ZERO(&lj);
    double v = 0;
    li.Add(&v);
    srf->MakeTriangulationGridInto(&li, 0, 1, true);
    lj.Add(&v);
    srf->MakeTriangulationGridInto(&lj, 0, 1, false);

    // Now iterate over each quad in the grid. If it's outside the polygon,
    // or if it intersects the polygon, then we discard it. Otherwise we
    // generate two triangles in the mesh, and cut it out of our polygon.
    int i, j;
    for(i = 0; i < (li.n - 1); i++) {
        for(j = 0; j < (lj.n - 1); j++) {
            double us = li.elem[i], uf = li.elem[i+1],
                   vs = lj.elem[j], vf = lj.elem[j+1];

            Vector a = Vector::From(us, vs, 0),
                   b = Vector::From(us, vf, 0),
                   c = Vector::From(uf, vf, 0),
                   d = Vector::From(uf, vs, 0);

            if(orig.AnyEdgeCrossings(a, b, NULL) ||
               orig.AnyEdgeCrossings(b, c, NULL) ||
               orig.AnyEdgeCrossings(c, d, NULL) ||
               orig.AnyEdgeCrossings(d, a, NULL))
            {
                continue;
            }

            // There's no intersections, so it doesn't matter which point
            // we decide to test.
            if(!this->ContainsPoint(a)) {
                continue;
            }

            // Add the quad to our mesh
            STriangle tr;
            ZERO(&tr);
            tr.a = a;
            tr.b = b;
            tr.c = c;
            mesh->AddTriangle(&tr);
            tr.a = a;
            tr.b = c;
            tr.c = d;
            mesh->AddTriangle(&tr);

            holes.AddEdge(a, b);
            holes.AddEdge(b, c);
            holes.AddEdge(c, d);
            holes.AddEdge(d, a);
        }
    }

    holes.CullExtraneousEdges();
    SPolygon hp;
    ZERO(&hp);
    holes.AssemblePolygon(&hp, NULL, true);

    SContour *sc;
    for(sc = hp.l.First(); sc; sc = hp.l.NextAfter(sc)) {
        l.Add(sc);
    }

    orig.Clear();
    holes.Clear();
    li.Clear();
    lj.Clear();
    hp.l.Clear();

    UvTriangulateInto(mesh, srf);
}
Пример #2
0
void SolveSpace::ExportSectionTo(char *filename) {
    Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
    gn = gn.WithMagnitude(1);

    Group *g = SK.GetGroup(SS.GW.activeGroup);
    g->GenerateDisplayItems();
    if(g->displayMesh.IsEmpty()) {
        Error("No solid model present; draw one with extrudes and revolves, "
              "or use Export 2d View to export bare lines and curves.");
        return;
    }
    
    // The plane in which the exported section lies; need this because we'll
    // reorient from that plane into the xy plane before exporting.
    Vector origin, u, v, n;
    double d;

    SS.GW.GroupSelection();
#define gs (SS.GW.gs)
    if((gs.n == 0 && g->activeWorkplane.v != Entity::FREE_IN_3D.v)) {
        Entity *wrkpl = SK.GetEntity(g->activeWorkplane);
        origin = wrkpl->WorkplaneGetOffset();
        n = wrkpl->Normal()->NormalN();
        u = wrkpl->Normal()->NormalU();
        v = wrkpl->Normal()->NormalV();
    } else if(gs.n == 1 && gs.faces == 1) {
        Entity *face = SK.GetEntity(gs.entity[0]);
        origin = face->FaceGetPointNum();
        n = face->FaceGetNormalNum();
        if(n.Dot(gn) < 0) n = n.ScaledBy(-1);
        u = n.Normal(0);
        v = n.Normal(1);
    } else if(gs.n == 3 && gs.vectors == 2 && gs.points == 1) {
        Vector ut = SK.GetEntity(gs.entity[0])->VectorGetNum(),
               vt = SK.GetEntity(gs.entity[1])->VectorGetNum();
        ut = ut.WithMagnitude(1);
        vt = vt.WithMagnitude(1);

        if(fabs(SS.GW.projUp.Dot(vt)) < fabs(SS.GW.projUp.Dot(ut))) {
            SWAP(Vector, ut, vt);
        }
        if(SS.GW.projRight.Dot(ut) < 0) ut = ut.ScaledBy(-1);
        if(SS.GW.projUp.   Dot(vt) < 0) vt = vt.ScaledBy(-1);

        origin = SK.GetEntity(gs.point[0])->PointGetNum();
        n = ut.Cross(vt);
        u = ut.WithMagnitude(1);
        v = (n.Cross(u)).WithMagnitude(1);
    } else {
        Error("Bad selection for export section. Please select:\n\n"
              "    * nothing, with an active workplane "
                        "(workplane is section plane)\n"
              "    * a face (section plane through face)\n"
              "    * a point and two line segments "
                        "(plane through point and parallel to lines)\n");
        return;
    }
    SS.GW.ClearSelection();

    n = n.WithMagnitude(1);
    d = origin.Dot(n);

    SEdgeList el;
    ZERO(&el);
    SBezierList bl;
    ZERO(&bl);

    // If there's a mesh, then grab the edges from it.
    g->runningMesh.MakeEdgesInPlaneInto(&el, n, d);

    // If there's a shell, then grab the edges and possibly Beziers.
    g->runningShell.MakeSectionEdgesInto(n, d,
       &el, 
       (SS.exportPwlCurves || fabs(SS.exportOffset) > LENGTH_EPS) ? NULL : &bl);

    // All of these are solid model edges, so use the appropriate style.
    SEdge *se;
    for(se = el.l.First(); se; se = el.l.NextAfter(se)) {
        se->auxA = Style::SOLID_EDGE;
    }
    SBezier *sb;
    for(sb = bl.l.First(); sb; sb = bl.l.NextAfter(sb)) {
        sb->auxA = Style::SOLID_EDGE;
    }

    el.CullExtraneousEdges();
    bl.CullIdenticalBeziers();

    // And write the edges.
    VectorFileWriter *out = VectorFileWriter::ForFile(filename);
    if(out) {
        // parallel projection (no perspective), and no mesh
        ExportLinesAndMesh(&el, &bl, NULL,
                           u, v, n, origin, 0,
                           out);
    }
    el.Clear();
    bl.Clear();
}