protected void ProcessPendingRoutImplementation(ImplicitNaryDifference3d processedSide, AxisAlignedBox3d filterBox, Action <DMesh3> setProcessedMesh) { DMesh3 mesh = GenerateMeshBase(processedSide, filterBox); MeshPlaneCut cut = new MeshPlaneCut(mesh, Center.ToVector3d() + (Vector3d.AxisZ * SizeZ / 2.0), Vector3d.AxisZ); bool bc = cut.Cut(); if (!mesh.IsCompact) { mesh.CompactInPlace(); } setProcessedMesh(mesh); }
private void CutSectionSide(DMesh3 mesh, Vector3d origin, Vector3d direction, bool fill) { MeshPlaneCut cut = new MeshPlaneCut(mesh, origin, direction); bool bc = cut.Cut(); if (fill) { PlanarHoleFiller filler = new PlanarHoleFiller(cut) { FillTargetEdgeLen = _cubeSize }; bool bf = filler.Fill(); } }
public bool Compute() { DMesh3 copy = new DMesh3(Mesh); //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS); Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis); MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal); cut.Cut(); Loops = new DCurve3[cut.CutLoops.Count]; for (int li = 0; li < cut.CutLoops.Count; ++li) { EdgeLoop edgeloop = cut.CutLoops[li]; DCurve3 loop = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices); // [TODO] collapse degenerate points... if (NormalOffset > 0) { for (int i = 0; i < loop.VertexCount; ++i) { Vector3f n = Vector3f.Zero; if (copy.HasVertexNormals) { n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]); } else { n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]); } n -= n.Dot(PlaneNormal) * PlaneNormal; n.Normalize(); loop[i] += NormalOffset * (Vector3d)n; } } Loops[li] = loop; } return(Loops.Length > 0); }
} // test_basic_fills public static void test_plane_cut() { List <int> tests = new List <int>() { 1 }; bool DO_EXHAUSTIVE_TESTS = false; foreach (int num_test in tests) { string name; DMesh3 orig_mesh = MakeEditTestMesh(num_test, out name); DMesh3 mesh = new DMesh3(orig_mesh); AxisAlignedBox3d bounds = mesh.CachedBounds; MeshPlaneCut cut = new MeshPlaneCut(mesh, bounds.Center, Vector3d.AxisY); Debug.Assert(cut.Validate() == ValidationStatus.Ok); bool bCutOK = cut.Cut(); System.Console.Write("cut: {0} loops: {1} spans: {2}", ((bCutOK) ? "Ok" : "Failed"), cut.CutLoops.Count, cut.CutSpans.Count); foreach (var loop in cut.CutLoops) { loop.CheckValidity(FailMode.gDevAssert); } foreach (var span in cut.CutSpans) { span.CheckValidity(FailMode.gDevAssert); } bool bFillOK = cut.FillHoles(-1); System.Console.WriteLine(" fill: {0}", ((bFillOK) ? "Ok" : "Failed")); TestUtil.WriteTestOutputMesh(mesh, name + "_cut" + ".obj"); if (DO_EXHAUSTIVE_TESTS == false) { continue; } // grinder: cut through each vtx int VertexIncrement = 1; for (int vid = 0; vid < orig_mesh.MaxVertexID; vid += VertexIncrement) { if (orig_mesh.IsVertex(vid) == false) { continue; } if (vid % 100 == 0) { System.Console.WriteLine("{0} / {1}", vid, orig_mesh.MaxVertexID); } Vector3d v = orig_mesh.GetVertex(vid); mesh = new DMesh3(orig_mesh); cut = new MeshPlaneCut(mesh, v, Vector3d.AxisY); bCutOK = cut.Cut(); Debug.Assert(bCutOK); } } // test_plane_cut }
public static void test_arrangement_demo() { DMesh3 mesh = TestUtil.LoadTestInputMesh("spheres_and_planes.obj"); MeshTransforms.Scale(mesh, 8); AxisAlignedBox3d meshBounds = mesh.CachedBounds; Vector3d origin = meshBounds.Center; double simplify_thresh = 5.0; Frame3f plane = new Frame3f(origin, Vector3d.AxisY); MeshPlaneCut cut = new MeshPlaneCut(mesh, plane.Origin, plane.Z); cut.Cut(); Arrangement2d builder = new Arrangement2d(new AxisAlignedBox2d(1024.0)); // insert all cut edges HashSet <Vector2d> srcpts = new HashSet <Vector2d>(); foreach (EdgeLoop loop in cut.CutLoops) { Polygon2d poly = new Polygon2d(); foreach (int vid in loop.Vertices) { poly.AppendVertex(mesh.GetVertex(vid).xz); } poly.Simplify(simplify_thresh, 0.01, true); foreach (Vector2d v in poly.Vertices) { srcpts.Add(v); } builder.Insert(poly); } foreach (EdgeSpan span in cut.CutSpans) { PolyLine2d pline = new PolyLine2d(); foreach (int vid in span.Vertices) { pline.AppendVertex(mesh.GetVertex(vid).xz); } pline.Simplify(simplify_thresh, 0.01, true); foreach (Vector2d v in pline) { srcpts.Add(v); } builder.Insert(pline); } SVGWriter svg = new SVGWriter(); svg.AddGraph(builder.Graph); var vtx_style = SVGWriter.Style.Outline("red", 1.0f); foreach (int vid in builder.Graph.VertexIndices()) { Vector2d v = builder.Graph.GetVertex(vid); if (srcpts.Contains(v) == false) { svg.AddCircle(new Circle2d(v, 2), vtx_style); } } svg.Write(TestUtil.GetTestOutputPath("arrangement.svg")); }
// appends connector to mesh. This one is messy bool compute_connector(DMesh3 mesh) { if (DebugStep <= 2) { return(true); } AxisAlignedBox3d socketBounds = mesh.CachedBounds; Vector3d c = socketBounds.Center; c.y = socketBounds.Min.y + ConnectorCutHeight; /* * first we select the outer shell triangles, and plane-cut them some ways up from the bottom. * This creates an open loop that we hang onto */ MeshPlaneCut outer_cut = new MeshPlaneCut(mesh, c, CutPlaneNormal); outer_cut.CutFaceSet = new MeshFaceSelection(mesh, LastExtrudeOuterGroupID); outer_cut.Cut(); MeshPlaneCut inner_cut = null; if (Connector.HasInner) { inner_cut = new MeshPlaneCut(mesh, c, CutPlaneNormal); inner_cut.CutFaceSet = new MeshFaceSelection(mesh, LastInnerGroupID); inner_cut.Cut(); } if (DebugStep <= 3) { return(true); } // save the loops we created EdgeLoop outerCutLoop = outer_cut.CutLoops[0]; EdgeLoop innerCutLoop = (inner_cut != null) ? inner_cut.CutLoops[0] : null; AxisAlignedBox3d cutLoopBounds = BoundsUtil.Bounds(outerCutLoop.Vertices, (vid) => { return(mesh.GetVertex(vid)); }); /* * Now we append the connector mesh and find its open loop */ // figure out where we want to position connector (which will be centered below origin) double dy = 0; // socketBounds.Min.y; if (socketBounds.Min.y < 0) { dy = socketBounds.Min.y + 5.0; } Vector3d shiftxz = Vector3d.Zero;// new Vector3d(cutLoopBounds.Center.x, 0, cutLoopBounds.Center.z); Vector3d shiftxyz = shiftxz + dy * Vector3d.AxisY; // append the connector // [TODO] do we need to hold the lock this entire time? I guess so since it would // be a disaster if connector changes... bool bConnectorOK = true; lock (connector_lock) { SocketConnector.AppendInfo append_info = Connector.AppendConnectorTo(mesh, shiftxyz); if (DebugStep <= 4) { return(true); } // [TODO] push out of inner offset here... if (Connector.HasInner) { merge_loops(mesh, innerCutLoop, append_info.InnerLoop, false); } // [TODO] in addition to pushing out of outer offset, we should also make sure // we are far enough away from inner merge surface... merge_loops(mesh, outerCutLoop, append_info.OuterLoop, true); bConnectorOK = Connector.CutHoles(mesh, shiftxyz); if (bConnectorOK == false) { f3.DebugUtil.Log("Connector.CutHoles failed!"); } } return(bConnectorOK); }
// exports svg w/ different containments of point set (created by slicing mesh) public static void containment_demo_svg() { DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); MeshTransforms.Scale(mesh, 4); AxisAlignedBox3d meshBounds = mesh.CachedBounds; Vector3d origin = meshBounds.Center; origin -= 0.2 * meshBounds.Height * Vector3d.AxisY; Frame3f plane = new Frame3f(origin, new Vector3d(1, 3, 0).Normalized); MeshPlaneCut cut = new MeshPlaneCut(mesh, plane.Origin, plane.Z); cut.Cut(); AxisAlignedBox2d polyBounds = AxisAlignedBox2d.Empty; List <Polygon2d> polys = new List <Polygon2d>(); foreach (EdgeLoop loop in cut.CutLoops) { Polygon2d poly = new Polygon2d(); foreach (int vid in loop.Vertices) { poly.AppendVertex(mesh.GetVertex(vid).xz); } poly.Rotate(new Matrix2d(90, true), Vector2d.Zero); polys.Add(poly); polyBounds.Contain(poly.Bounds); } SVGWriter svg = new SVGWriter(); var polyStyle = SVGWriter.Style.Outline("red", 1.0f); var contStyle = SVGWriter.Style.Outline("black", 1.0f); for (int k = 0; k < 3; ++k) { double shift = (k == 2) ? 1.4f : 1.1f; Vector2d tx = (k - 1) * (polyBounds.Width * shift) * Vector2d.AxisX; List <Vector2d> pts = new List <Vector2d>(); foreach (Polygon2d poly in polys) { var p2 = new Polygon2d(poly).Translate(tx); pts.AddRange(p2.Vertices); svg.AddPolygon(p2, polyStyle); } if (k == 0) { ConvexHull2 hull = new ConvexHull2(pts, 0.001, QueryNumberType.QT_DOUBLE); svg.AddPolygon(hull.GetHullPolygon(), contStyle); } else if (k == 1) { ContMinBox2 contbox = new ContMinBox2(pts, 0.001, QueryNumberType.QT_DOUBLE, false); svg.AddPolygon(new Polygon2d(contbox.MinBox.ComputeVertices()), contStyle); } else if (k == 2) { ContMinCircle2 contcirc = new ContMinCircle2(pts); svg.AddCircle(contcirc.Result, contStyle); } } svg.Write(TestUtil.GetTestOutputPath("contain_demos.svg")); }