public DMesh3 BooleanUnion(DMesh3 mesh1, DMesh3 mesh2) { BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 128, 0.2f); BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 128, 0.2f); //take the difference of the bolus mesh minus the tools var mesh = new ImplicitUnion3d() { A = meshA, B = meshB }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / 96; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); //int triangleCount = c.Mesh.TriangleCount / 2; //Reducer r = new Reducer(c.Mesh); //r.ReduceToTriangleCount(triangleCount); return(c.Mesh); }
private static DMesh3 BooleanIntersection(DMesh3 mesh1, DMesh3 mesh2) { BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 64, 0.2f); BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 64, 0.2f); //take the intersection of the meshes minus the tools ImplicitIntersection3d mesh = new ImplicitIntersection3d() { A = meshA, B = meshB }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / 128; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); int triangleCount = c.Mesh.TriangleCount / 2; Reducer r = new Reducer(c.Mesh); r.ReduceToTriangleCount(triangleCount); return(c.Mesh); }
//experimental public List <DMesh3> SliceMold(DMesh3 mesh_to_slice, int number_of_slices) { var meshes = new List <MeshGeometry3D>(); //convert mesh to DMesh DMesh3 mesh = mesh_to_slice; //create cube for slicing double z_height = mesh.GetBounds().Max.z - mesh.GetBounds().Min.z; double slice_interval = (double)(z_height / number_of_slices); double x_size = mesh.GetBounds().Depth; double y_size = mesh.GetBounds().Width; double low_z = mesh.GetBounds().Min.z; //boolean intersection each mesh var sliced_meshes = new List <DMesh3>(); for (int i = 0; i < number_of_slices; i++) { //create box Vector3d centre = new Vector3d(0, 0, low_z + slice_interval / 2 + i * (slice_interval)); Vector3d extend = new Vector3d( x_size, y_size, slice_interval / 2); ImplicitBox3d box = new ImplicitBox3d() { Box = new Box3d(centre, extend) }; //boolean overlap BoundedImplicitFunction3d meshA = meshToImplicitF(mesh, 64, 0.2f); //take the difference of the bolus mesh minus the tools ImplicitIntersection3d mesh_result = new ImplicitIntersection3d { A = meshA, B = box }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh_result; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh_result.Bounds(); c.CubeSize = c.Bounds.MaxDim / 256; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); int triangleCount = c.Mesh.TriangleCount / 3; Reducer r = new Reducer(c.Mesh); r.ReduceToTriangleCount(triangleCount); sliced_meshes.Add(c.Mesh); } return(sliced_meshes); }
void sample_min(BoundedImplicitFunction3d f, IEnumerable <Vector3i> indices) { gParallel.ForEach(indices, (idx) => { Vector3d v = Indexer.FromGrid(idx); double d = f.Value(ref v); Grid.set_min(ref idx, (float)d); }); }
public static ImplicitUnion3d ImplicitUnion(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB) { var union = new ImplicitUnion3d() { A = meshA, B = meshB }; return(union); }
public static ImplicitIntersection3d ImplicitIntersection(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB) { var intersection = new ImplicitIntersection3d() { A = meshA, B = meshB }; return(intersection); }
public static ImplicitBlend3d ImplicitBlend(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB, double blend) { var blendMesh = new ImplicitBlend3d() { A = meshA, B = meshB, Blend = blend }; return(blendMesh); }
public static ImplicitOffset3d ImplicitOffset(BoundedImplicitFunction3d mesh, double offset) { var offsetMesh = new ImplicitOffset3d() { A = mesh, Offset = offset }; return(offsetMesh); }
public static ImplicitSmoothDifference3d ImplicitSmoothDifference(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB) { var smoothMesh = new ImplicitSmoothDifference3d() { A = meshA, B = meshB }; return(smoothMesh); }
public static ImplicitDifference3d ImplicitDifference(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB) { var diff = new ImplicitDifference3d() { A = meshA, B = meshB }; return(diff); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { // INPUT // declaration Rhino.Geometry.Mesh meshA = null; Rhino.Geometry.Mesh meshB = null; int num = 0; double offset = 0.00; double blend = 1.00; bool runIt = false; bool showIt = false; bool writeObj = false; string path = null; DA.GetData(0, ref meshA); DA.GetData(1, ref meshB); DA.GetData(2, ref num); DA.GetData(3, ref blend); DA.GetData(4, ref offset); DA.GetData(5, ref runIt); DA.GetData(6, ref showIt); DA.GetData(7, ref writeObj); DA.GetData(8, ref path); // run if (runIt) { DMesh3 g3MeshA = ConvertDMesh(meshA); DMesh3 g3MeshB = ConvertDMesh(meshB); BoundedImplicitFunction3d implicitA = MeshMorphoLib.MeshClassFnc.MeshToImplicitF(g3MeshA, num, offset); BoundedImplicitFunction3d implicitB = MeshMorphoLib.MeshClassFnc.MeshToImplicitF(g3MeshB, num, offset); var implicitBlendDone = MeshMorphoLib.MeshClassFnc.ImplicitBlend(implicitA, implicitB, blend); DMesh3 newMesh = MeshMorphoLib.MeshClassFnc.GenerateMeshF(implicitBlendDone, num); if (showIt) { Rhino.Geometry.Mesh resultMesh = MeshMorphoLib.MeshIntegration.ConvertToRhinoMesh(newMesh); DA.SetData(0, resultMesh); } if (writeObj) { try { string fullFolder = System.IO.Path.Combine(path, "MorphoModel.obj"); MeshClassIO.WriteMesh(newMesh, fullFolder); DA.SetData(1, fullFolder); } catch { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Please provide a valid path."); } } } }
private DMesh3 GenerateMeshBase(BoundedImplicitFunction3d root, AxisAlignedBox3d filterBox) { MarchingCubes c = new MarchingCubes(); c.Implicit = root; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = filterBox; //_sideFilterBox; c.CubeSize = _cubeSize / 4.0; c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); }
// generateMeshF() meshes the input implicit function at // the given cell resolution, and writes out the resulting mesh DMesh3 generatMeshF(BoundedImplicitFunction3d root, int numcells) { MarchingCubes c = new MarchingCubes(); c.Implicit = root; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = root.Bounds(); c.CubeSize = c.Bounds.MaxDim / numcells; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); // write mesh }
public void SetSources(List <DMeshSourceOp> sources) { if (mesh_sources != null) { throw new Exception("todo: handle changing sources!"); } mesh_sources = new List <DMeshSourceOp>(sources); foreach (var source in mesh_sources) { source.OperatorModified += on_input_modified; } cached_sdfs = new MeshSignedDistanceGrid[sources.Count]; cached_isos = new BoundedImplicitFunction3d[sources.Count]; invalidate(); }
public static DMesh3 GenerateMeshF(BoundedImplicitFunction3d mesh, int num_cells) { MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / num_cells; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals DMesh3 outputMesh = c.Mesh; return(outputMesh); }
void generate_mesh(DenseGrid3f supportGrid, DenseGridTrilinearImplicit distanceField) { DenseGridTrilinearImplicit volume = new DenseGridTrilinearImplicit( supportGrid, GridOrigin, CellSize); BoundedImplicitFunction3d inputF = volume; if (SubtractMesh) { BoundedImplicitFunction3d sub = distanceField; if (SubtractMeshOffset > 0) { sub = new ImplicitOffset3d() { A = distanceField, Offset = SubtractMeshOffset } } ; ImplicitDifference3d subtract = new ImplicitDifference3d() { A = volume, B = sub }; inputF = subtract; } ImplicitHalfSpace3d cutPlane = new ImplicitHalfSpace3d() { Origin = Vector3d.Zero, Normal = Vector3d.AxisY }; ImplicitDifference3d cut = new ImplicitDifference3d() { A = inputF, B = cutPlane }; MarchingCubes mc = new MarchingCubes() { Implicit = cut, Bounds = grid_bounds, CubeSize = CellSize }; mc.Bounds.Min.y = -2 * mc.CubeSize; mc.Bounds.Min.x -= 2 * mc.CubeSize; mc.Bounds.Min.z -= 2 * mc.CubeSize; mc.Bounds.Max.x += 2 * mc.CubeSize; mc.Bounds.Max.z += 2 * mc.CubeSize; mc.Generate(); SupportMesh = mc.Mesh; } }
public void AddToolApplication(BoundedImplicitFunction3d toolApplication) { bool notify = false; lock (_lockObj) { if (_toolApplications == null) { _toolApplications = new List <BoundedImplicitFunction3d>(); notify = true; } } _toolApplications.Add(toolApplication); if (notify) { RisePropertyChanged(nameof(IsCorrupted)); } }
private static DMesh3 GenerateMeshF(BoundedImplicitFunction3d root, int numcells) { var bounds = root.Bounds(); var c = new MarchingCubes() { Implicit = root, RootMode = MarchingCubes.RootfindingModes.LerpSteps, // cube-edge convergence method RootModeSteps = 5, // number of iterations Bounds = bounds, CubeSize = bounds.MaxDim / numcells, }; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); }
internal Task <bool> ApplyActionAsync(BoundedImplicitFunction3d toolApplication) { return(Task.Run(async() => { AddToolApplication(toolApplication); try { InternalGeometry = await Task.Run(() => GenerateMesh()); OnActionApplied(); return true; } catch (System.Exception) { return false; } })); }
public void Sample(BoundedImplicitFunction3d f, double expandRadius = 0) { AxisAlignedBox3d bounds = f.Bounds(); Vector3d expand = expandRadius * Vector3d.One; Vector3i gridMin = Indexer.ToGrid(bounds.Min - expand), gridMax = Indexer.ToGrid(bounds.Max + expand) + Vector3i.One; gridMin = GridBounds.ClampExclusive(gridMin); gridMax = GridBounds.ClampExclusive(gridMax); AxisAlignedBox3i gridbox = new AxisAlignedBox3i(gridMin, gridMax); switch (CombineMode) { case CombineModes.DistanceMinUnion: sample_min(f, gridbox.IndicesInclusive()); break; } }
public void SetSources(List <DMeshSourceOp> sources) { if (mesh_sources != null) { throw new Exception("MeshVoxelBlendOp.SetSources: handle changing sources!"); } //if (sources.Count != 2) // throw new Exception("MeshVoxelBlendOp.SetSources: only two sources supported!"); mesh_sources = new List <DMeshSourceOp>(sources); foreach (var source in mesh_sources) { source.OperatorModified += on_input_modified; } cached_sdfs = new MeshSignedDistanceGrid[sources.Count]; cached_isos = new BoundedImplicitFunction3d[sources.Count]; cached_bvtrees = new DMeshAABBTreePro[sources.Count]; invalidate(); }
protected virtual void compute_shell_distancefield() { if (cached_is_closed == false) { compute_shell_distancefield_unsigned(); return; } double offset_distance = shell_thickness; Interval1d shell_range = new Interval1d(0, offset_distance); if (shell_direction == ShellDirections.Symmetric) { shell_range = new Interval1d(-offset_distance / 2, offset_distance / 2); } else if (shell_direction == ShellDirections.Inner) { shell_range = new Interval1d(-offset_distance, 0); offset_distance = -offset_distance; } if (cached_sdf == null || shell_thickness > cached_sdf_max_offset || grid_cell_size != cached_sdf.CellSize) { DMesh3 meshIn = MeshSource.GetDMeshUnsafe(); int exact_cells = (int)((shell_thickness) / grid_cell_size) + 1; // only use spatial DS if we are computing enough cells DMeshAABBTree3 use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z); MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial) { ExactBandWidth = exact_cells }; if (use_spatial != null) { sdf.NarrowBandMaxDistance = shell_thickness + grid_cell_size; sdf.ComputeMode = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill; } sdf.CancelF = is_invalidated; sdf.Compute(); if (is_invalidated()) { return; } cached_sdf = sdf; cached_sdf_max_offset = shell_thickness; cached_sdf_bounds = meshIn.CachedBounds; } var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize); BoundedImplicitFunction3d shell_field = (shell_direction == ShellDirections.Symmetric) ? (BoundedImplicitFunction3d) new ImplicitShell3d() { A = iso, Inside = shell_range } : (BoundedImplicitFunction3d) new ImplicitOffset3d() { A = iso, Offset = offset_distance }; //var shell_field = new ImplicitShell3d() { A = iso, Inside = shell_range }; //BoundedImplicitFunction3d shell_field = (signed_field) ? // (BoundedImplicitFunction3d)new ImplicitShell3d() { A = iso, Inside = shell_range } : // (BoundedImplicitFunction3d)new ImplicitOffset3d() { A = iso, Offset = offset_distance }; //ImplicitOffset3d offset = new ImplicitOffset3d() { A = iso, Offset = offset_distance }; MarchingCubes c = new MarchingCubes(); c.Implicit = shell_field; c.IsoValue = 0; c.Bounds = cached_sdf_bounds; c.CubeSize = mesh_cell_size; c.Bounds.Expand(offset_distance + 3 * c.CubeSize); c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.CancelF = is_invalidated; c.Generate(); if (is_invalidated()) { return; } Reducer r = new Reducer(c.Mesh); r.FastCollapsePass(c.CubeSize * 0.5, 3, true); if (is_invalidated()) { return; } if (min_component_volume > 0) { MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume); } if (is_invalidated()) { return; } if (shell_surface_only) { if (shell_direction == ShellDirections.Inner || shell_direction == ShellDirections.Outer) { c.Mesh.AttachMetadata("is_partial", new object()); } } ResultMesh = c.Mesh; }
public static void test_marching_cubes_implicits() { DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); MeshTransforms.Translate(mesh, -mesh.CachedBounds.Center); double meshCellsize = mesh.CachedBounds.MaxDim / 32; MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(mesh, meshCellsize); levelSet.ExactBandWidth = 3; levelSet.UseParallel = true; levelSet.ComputeMode = MeshSignedDistanceGrid.ComputeModes.NarrowBandOnly; levelSet.Compute(); var meshIso = new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize); ImplicitOffset3d offsetMeshIso = new ImplicitOffset3d() { A = meshIso, Offset = 2.0 }; double r = 15.0; ImplicitSphere3d sphere1 = new ImplicitSphere3d() { Origin = Vector3d.Zero, Radius = r }; ImplicitSphere3d sphere2 = new ImplicitSphere3d() { Origin = r * Vector3d.AxisX, Radius = r }; ImplicitAxisAlignedBox3d aabox1 = new ImplicitAxisAlignedBox3d() { AABox = new AxisAlignedBox3d(r * 0.5 * Vector3d.One, r, r * 0.75, r * 0.5) }; ImplicitBox3d box1 = new ImplicitBox3d() { Box = new Box3d(new Frame3f(r * 0.5 * Vector3d.One, Vector3d.One.Normalized), new Vector3d(r, r * 0.75, r * 0.5)) }; ImplicitLine3d line1 = new ImplicitLine3d() { Segment = new Segment3d(Vector3d.Zero, r * Vector3d.One), Radius = 3.0 }; ImplicitHalfSpace3d half1 = new ImplicitHalfSpace3d() { Origin = Vector3d.Zero, Normal = Vector3d.One.Normalized }; ImplicitUnion3d union = new ImplicitUnion3d() { A = sphere1, B = line1 }; ImplicitDifference3d difference = new ImplicitDifference3d() { A = meshIso, B = aabox1 }; ImplicitIntersection3d intersect = new ImplicitIntersection3d() { A = meshIso, B = half1 }; ImplicitNaryUnion3d nunion = new ImplicitNaryUnion3d() { Children = new List <BoundedImplicitFunction3d>() { offsetMeshIso, sphere1, sphere2 } }; ImplicitNaryDifference3d ndifference = new ImplicitNaryDifference3d() { A = offsetMeshIso, BSet = new List <BoundedImplicitFunction3d>() { sphere1, sphere2 } }; ImplicitBlend3d blend = new ImplicitBlend3d() { A = sphere1, B = sphere2 }; BoundedImplicitFunction3d root = intersect; AxisAlignedBox3d bounds = root.Bounds(); int numcells = 64; MarchingCubes c = new MarchingCubes(); c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Implicit = root; c.Bounds = bounds; c.CubeSize = bounds.MaxDim / numcells; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); TestUtil.WriteTestOutputMesh(c.Mesh, "marching_cubes_implicit.obj"); }
public void ApplyAction(BoundedImplicitFunction3d toolApplication) { AddToolApplication(toolApplication); InternalGeometry = GenerateMesh(); OnActionApplied(); }
protected virtual DMesh3 compute_wrap() { cache_input_sdfs(); if (is_invalidated()) { return(null); } BoundedImplicitFunction3d iso = null; if (op_type == OpTypes.Union) { iso = new ImplicitNaryUnion3d() { Children = new List <BoundedImplicitFunction3d>(cached_isos) }; } else if (op_type == OpTypes.Intersection) { iso = new ImplicitNaryIntersection3d() { Children = new List <BoundedImplicitFunction3d>(cached_isos) }; } else if (op_type == OpTypes.Difference) { iso = new ImplicitNaryDifference3d() { A = cached_isos[0], BSet = new List <BoundedImplicitFunction3d>(cached_isos.Skip(1)) }; } MarchingCubes c = new MarchingCubes(); c.Implicit = iso; c.IsoValue = 0; c.Bounds = iso.Bounds(); c.CubeSize = mesh_cell_size; c.Bounds.Expand(3 * c.CubeSize); c.RootMode = MarchingCubes.RootfindingModes.Bisection; c.RootModeSteps = 5; c.CancelF = is_invalidated; c.Generate(); if (is_invalidated()) { return(null); } Reducer r = new Reducer(c.Mesh); r.FastCollapsePass(c.CubeSize / 2, 3, true); if (is_invalidated()) { return(null); } if (min_component_volume > 0) { MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume); } if (is_invalidated()) { return(null); } return(c.Mesh); }