public int SanityCheck() { if (isImported) { return(0); } var tree = new DMeshAABBTree3(cuttingInfo.oldMesh, true); //todo build tree earlier?? var errors = 0; foreach (var keyValuePair in cuttingInfo.PointToPoint) { if (!mesh.IsVertex(keyValuePair.Key)) { Debug.Log($"NonVertex from {cuttingInfo.data.algo.ToString()}"); } var coords = mesh.GetVertex(keyValuePair.Key); var oldMesh = cuttingInfo.oldMesh; if (!tree.IsInside(coords)) { errors++; } } return(errors); }
/// <summary> /// Checks if a point is inside of a mesh. This function is slow due to the need to build a spatial data structure using geometry3Sharp. /// </summary> /// <param name="mesh">The mesh to be checked.</param> /// <param name="point">The point in question.</param> /// <returns>Whether the point is inside the mesh.</returns> public static bool IsPointInside(this Mesh mesh, Vector3 point) { var mesh3 = GenerateDynamicMesh(mesh.vertices, mesh.triangles, mesh.normals); var spatial = new DMeshAABBTree3(mesh3); spatial.Build(); return(spatial.IsInside(new Vector3d(point.x, point.y, point.z))); }
public Vector3d Project(Vector3d vPoint, int identifier) { if (Spatial.IsInside(vPoint)) { return(MeshQueries.NearestPointFrame(Spatial.Mesh, Spatial, vPoint).Origin); } else { return(vPoint); } }
protected override void SolveInstance(IGH_DataAccess DA) { int num_cells = 128; DMesh3_goo dMsh_goo = null; DA.GetData(0, ref dMsh_goo); DA.GetData(1, ref num_cells); DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value); double cell_size = dMsh_copy.CachedBounds.MaxDim / num_cells; DMeshAABBTree3 spatial = new DMeshAABBTree3(dMsh_copy, autoBuild: true); AxisAlignedBox3d bounds = dMsh_copy.CachedBounds; double cellsize = bounds.MaxDim / num_cells; ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min, cellsize); Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells)); foreach (Vector3i idx in bmp.Indices()) { g3.Vector3d v = indexer.FromGrid(idx); bmp.Set(idx, spatial.IsInside(v)); } VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator(); voxGen.Voxels = bmp; voxGen.Generate(); DMesh3 voxMesh = voxGen.Meshes[0]; var vecSize = dMsh_copy.CachedBounds.Extents; var box = dMsh_copy.GetBounds(); // Scale voxel mesh //MeshTransforms.Scale(voxMesh,) DA.SetData(0, voxMesh); }
internal Vector3d MovePointInsideAndAwayFromShell(CuttingInfo info, Vector3d position, int maxCount = 5) { var tree = new DMeshAABBTree3(info.mesh, true); if (!tree.IsInside(position)) { Debug.Log("Point outside of mesh"); var getInside = GetInsideShell(tree, position, info.data.ColorNum); if (getInside != null) { position += getInside.Value; Debug.Log($"GetInside. New Pos: {position} "); } else { Debug.Log("Point too far away from shell"); } } var getAway = this.GetAwayFromShellDirection(info, tree, position); int count = 0; while (getAway != null) { position += getAway.Value.Normalized * info.data.minDepth; Debug.Log($"Getaway. New Pos: {position} "); count++; if (count >= maxCount) { Debug.Log("MoveAway could not find a suitable position, count exceeded"); StaticFunctions.ErrorMessage("The object is too thin to find a suitable position. Might cause intersections."); break; } getAway = GetAwayFromShellDirection(info, tree, position); } return(position); }
public static DMesh3 MineCraft(DMesh3 mesh, int num_cells, out double scalefactor) { DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, autoBuild: true); AxisAlignedBox3d bounds = mesh.CachedBounds; double cellsize = bounds.MaxDim / num_cells; scalefactor = cellsize; ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min, cellsize); Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells)); foreach (Vector3i idx in bmp.Indices()) { g3.Vector3d v = indexer.FromGrid(idx); if (spatial.IsInside(v)) { bmp.Set(idx, true); } else { bmp.Set(idx, false); } } VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator(); voxGen.Voxels = bmp; voxGen.Generate(); DMesh3 voxMesh = voxGen.Meshes[0]; return(voxMesh); }
void constrained_smooth(DGraph3 graph, double surfDist, double dotThresh, double alpha, int rounds) { int NV = graph.MaxVertexID; Vector3d[] pos = new Vector3d[NV]; for (int ri = 0; ri < rounds; ++ri) { gParallel.ForEach(graph.VertexIndices(), (vid) => { Vector3d v = graph.GetVertex(vid); if (GroundVertices.Contains(vid) || TipVertices.Contains(vid)) { pos[vid] = v; return; } // for tip base vertices, we could allow them to move down and away within angle cone... if (TipBaseVertices.Contains(vid)) { pos[vid] = v; return; } // compute smoothed position of vtx Vector3d centroid = Vector3d.Zero; int nbr_count = 0; foreach (int nbr_vid in graph.VtxVerticesItr(vid)) { centroid += graph.GetVertex(nbr_vid); nbr_count++; } if (nbr_count == 1) { pos[vid] = v; return; } centroid /= nbr_count; Vector3d vnew = (1 - alpha) * v + (alpha) * centroid; // make sure we don't violate angle constraint to any nbrs int attempt = 0; try_again: foreach (int nbr_vid in graph.VtxVerticesItr(vid)) { Vector3d dv = graph.GetVertex(nbr_vid) - vnew; dv.Normalize(); double dot = dv.Dot(Vector3d.AxisY); if (Math.Abs(dot) < dotThresh) { if (attempt++ < 3) { vnew = Vector3d.Lerp(v, vnew, 0.66); goto try_again; } else { pos[vid] = v; return; } } } // offset from nearest point on surface Frame3f fNearest = MeshQueries.NearestPointFrame(Mesh, MeshSpatial, vnew, true); Vector3d vNearest = fNearest.Origin; double dist = vnew.Distance(vNearest); bool inside = MeshSpatial.IsInside(vnew); if (inside || dist < surfDist) { Vector3d normal = fNearest.Z; // don't push down? if (normal.Dot(Vector3d.AxisY) < 0) { normal.y = 0; normal.Normalize(); } vnew = fNearest.Origin + surfDist * normal; } pos[vid] = vnew; }); foreach (int vid in graph.VertexIndices()) { graph.SetVertex(vid, pos[vid]); } } }
public virtual bool Apply() { DMesh3 testAgainstMesh = Mesh; if (InsideMode == CalculationMode.RayParity) { MeshBoundaryLoops loops = new MeshBoundaryLoops(testAgainstMesh); if (loops.Count > 0) { testAgainstMesh = new DMesh3(Mesh); foreach (var loop in loops) { if (Cancelled()) { return(false); } SimpleHoleFiller filler = new SimpleHoleFiller(testAgainstMesh, loop); filler.Fill(); } } } DMeshAABBTree3 spatial = (Spatial != null && testAgainstMesh == Mesh) ? Spatial : new DMeshAABBTree3(testAgainstMesh, true); if (InsideMode == CalculationMode.AnalyticWindingNumber) { spatial.WindingNumber(Vector3d.Zero); } else if (InsideMode == CalculationMode.FastWindingNumber) { spatial.FastWindingNumber(Vector3d.Zero); } if (Cancelled()) { return(false); } // ray directions List <Vector3d> ray_dirs = null; int NR = 0; if (InsideMode == CalculationMode.SimpleOcclusionTest) { ray_dirs = new List <Vector3d>(); ray_dirs.Add(Vector3d.AxisX); ray_dirs.Add(-Vector3d.AxisX); ray_dirs.Add(Vector3d.AxisY); ray_dirs.Add(-Vector3d.AxisY); ray_dirs.Add(Vector3d.AxisZ); ray_dirs.Add(-Vector3d.AxisZ); NR = ray_dirs.Count; } Func <Vector3d, bool> isOccludedF = (pt) => { if (InsideMode == CalculationMode.RayParity) { return(spatial.IsInside(pt)); } else if (InsideMode == CalculationMode.AnalyticWindingNumber) { return(spatial.WindingNumber(pt) > WindingIsoValue); } else if (InsideMode == CalculationMode.FastWindingNumber) { return(spatial.FastWindingNumber(pt) > WindingIsoValue); } else { for (int k = 0; k < NR; ++k) { int hit_tid = spatial.FindNearestHitTriangle(new Ray3d(pt, ray_dirs[k])); if (hit_tid == DMesh3.InvalidID) { return(false); } } return(true); } }; bool cancel = false; BitArray vertices = null; if (PerVertex) { vertices = new BitArray(Mesh.MaxVertexID); MeshNormals normals = null; if (Mesh.HasVertexNormals == false) { normals = new MeshNormals(Mesh); normals.Compute(); } gParallel.ForEach(Mesh.VertexIndices(), (vid) => { if (cancel) { return; } if (vid % 10 == 0) { cancel = Cancelled(); } Vector3d c = Mesh.GetVertex(vid); Vector3d n = (normals == null) ? Mesh.GetVertexNormal(vid) : normals[vid]; c += n * NormalOffset; vertices[vid] = isOccludedF(c); }); } if (Cancelled()) { return(false); } RemovedT = new List <int>(); SpinLock removeLock = new SpinLock(); gParallel.ForEach(Mesh.TriangleIndices(), (tid) => { if (cancel) { return; } if (tid % 10 == 0) { cancel = Cancelled(); } bool inside = false; if (PerVertex) { Index3i tri = Mesh.GetTriangle(tid); inside = vertices[tri.a] || vertices[tri.b] || vertices[tri.c]; } else { Vector3d c = Mesh.GetTriCentroid(tid); Vector3d n = Mesh.GetTriNormal(tid); c += n * NormalOffset; inside = isOccludedF(c); } if (inside) { bool taken = false; removeLock.Enter(ref taken); RemovedT.Add(tid); removeLock.Exit(); } }); if (Cancelled()) { return(false); } if (RemovedT.Count > 0) { MeshEditor editor = new MeshEditor(Mesh); bool bOK = editor.RemoveTriangles(RemovedT, true); RemoveFailed = (bOK == false); } return(true); }
public static void test_Winding() { Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube() { EdgeVertices = 200 }; DMesh3 mesh = gen.Generate().MakeDMesh(); //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); GC.Collect(); double maxdim = mesh.CachedBounds.MaxDim; Vector3d center = mesh.CachedBounds.Center; var pts = TestUtil.RandomPoints3(100, new Random(31337), center, maxdim * 0.5); int num_inside = 0; foreach (Vector3d pt in pts) { bool inside = spatial.IsInside(pt); double distSqr = MeshQueries.TriDistanceSqr(mesh, spatial.FindNearestTriangle(pt), pt); double ptDist = pt.Length; double winding = mesh.WindingNumber(pt); double winding_2 = spatial.WindingNumber(pt); if (Math.Abs(winding - winding_2) > 0.00001) { System.Diagnostics.Debugger.Break(); } bool winding_inside = Math.Abs(winding) > 0.5; if (inside != winding_inside) { System.Diagnostics.Debugger.Break(); } if (inside) { num_inside++; } } System.Console.WriteLine("inside {0} / {1}", num_inside, pts.Length); // force rebuild for profiling code GC.Collect(); LocalProfiler p = new LocalProfiler(); pts = TestUtil.RandomPoints3(1000, new Random(31337), center, maxdim * 0.5); p.Start("full eval"); double sum = 0; foreach (Vector3d pt in pts) { double winding = mesh.WindingNumber(pt); sum += winding; } p.StopAll(); p.Start("tree build"); spatial = new DMeshAABBTree3(mesh, true); spatial.WindingNumber(Vector3d.Zero); p.StopAll(); GC.Collect(); GC.Collect(); p.Start("tree eval"); sum = 0; foreach (Vector3d pt in pts) { double winding = spatial.WindingNumber(pt); sum += winding; } p.StopAll(); System.Console.WriteLine(p.AllTimes()); }