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