├── .gitattributes ├── .gitignore ├── Examples ├── App.config ├── Examples.csproj ├── Gallery │ ├── 170720_Relief_02.gif │ └── h_01_3_zoom_2.png ├── Grasshopper │ ├── Distance_Transform.gh │ ├── Dynamic_Remesher.3dm │ ├── Dynamic_Remesher.gh │ ├── Funicular_Network.3dm │ ├── Funicular_Network.gh │ ├── Geodesic_Field.3dm │ ├── Geodesic_Field.gh │ ├── Geodesic_Field_3d.3dm │ ├── Geodesic_Field_3d.gh │ ├── HeMesh_Unroll.gh │ ├── IDWField_Example.3dm │ ├── IDWField_Example.gh │ ├── Noise_Field_Integration.gh │ ├── Quad_Strips.gh │ ├── Sort_Faces_By_Depth.gh │ ├── SphereCollide.3dm │ ├── Sphere_Collide.gh │ ├── Steiner_Tree_Finder.gh │ ├── User Objects │ │ └── SlurCS.ghuser │ └── Volumetric_Clustering.gh ├── HeMeshFromFile.cs ├── Paths.cs ├── PlanarizeHeMesh.cs ├── PlanarizeQuad.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── Images │ │ └── Geoff-McFetridge-Hands.png │ ├── chair_planar_0.obj │ ├── chair_smooth_0.obj │ ├── fabric_pucker_0.obj │ ├── fabric_pucker_1.obj │ ├── face_0.obj │ ├── face_mapped_0.obj │ ├── fortune_cookie_0.obj │ ├── minimal_0.obj │ ├── ring_crimped_0.obj │ ├── shell_low_poly_0.obj │ └── skeleton_0.obj └── packages.config ├── LICENSE.md ├── README.md ├── SlurGH ├── Components │ ├── Display │ │ ├── DisplayFaceColors.cs │ │ └── NormalShader.cs │ ├── Enums │ │ ├── DistanceMetrics.cs │ │ ├── FieldType.cs │ │ ├── NoiseType.cs │ │ └── SimState.cs │ ├── Mesh │ │ ├── AlignVertices.cs │ │ ├── MeshClosedPolyline.cs │ │ ├── MeshExtrude.cs │ │ ├── MeshFlip.cs │ │ ├── MeshLoft.cs │ │ ├── MeshLoftPair.cs │ │ └── MeshSeparate.cs │ └── SpatialSlur │ │ ├── Fields │ │ ├── CreateGridField.cs │ │ ├── CreateNoiseField.cs │ │ ├── EvaluateField.cs │ │ ├── GeodesicDistance.cs │ │ ├── IntegrateField.cs │ │ └── ResampleField.cs │ │ ├── Meshes │ │ ├── CreateDual.cs │ │ ├── EdgeLines.cs │ │ ├── FacePlanarity.cs │ │ ├── FacePolylines.cs │ │ ├── HeGraphFromLines.cs │ │ ├── HeMeshFromPolylines.cs │ │ ├── HeMeshUnroll.cs │ │ ├── HoleBoundaries.cs │ │ └── VertexPositions.cs │ │ └── Tools │ │ ├── CreateFeature.cs │ │ ├── DynamicRemesherSettings.cs │ │ └── DynamicRemesherSolver.cs ├── Params │ └── SpatialSlur │ │ ├── HeGraph3dParam.cs │ │ └── HeMesh3dParam.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── SlurGH.csproj ├── SlurGHInfo.cs └── Types │ ├── GH_HeGraph3d.cs │ └── GH_HeMesh3d.cs ├── SpatialSlur.sln └── SpatialSlur ├── Collections ├── ArrayView.cs ├── Extensions │ ├── ArrayExtensions.cs │ ├── ArrayViewExtensions.cs │ ├── IDictionaryExtensions.cs │ ├── IEnumerableExtensions.cs │ ├── IListExtensions.cs │ ├── IReadOnlyListExtensions.cs │ ├── ListExtensions.cs │ └── ReadOnlyArrayViewExtensions.cs ├── HashGrid2d.cs ├── HashGrid3d.cs ├── KMeans.cs ├── KdTree.cs ├── ListView.cs ├── PriorityQueue.cs ├── ProbabilitySelector.cs ├── Proximity.cs ├── QueueSet.cs ├── ReadOnlyArrayView.cs ├── ReadOnlyListView.cs ├── ReadOnlySet.cs ├── RefList.cs ├── Sequences.cs ├── StackSet.cs └── UniformPartitioner.cs ├── Core ├── Atomic.cs ├── AxisAngle3d.cs ├── ColorConversion.cs ├── Extensions │ ├── ColorExtensions.cs │ ├── GenericExtensions.cs │ └── RandomExtensions.cs ├── Geometry.cs ├── Interop.cs ├── Interval2d.cs ├── Interval3d.cs ├── Intervald.cs ├── Intervalf.cs ├── Matrix.cs ├── Matrix2d.cs ├── Matrix3d.cs ├── Matrix4d.cs ├── Orient2d.cs ├── Orient3d.cs ├── OrthoBasis2d.cs ├── OrthoBasis3d.cs ├── Plane3d.cs ├── Property.cs ├── Quaterniond.cs ├── SlurMath.cs ├── Templates │ ├── Matrix.cs │ ├── Matrix.tt │ ├── Vector.cs │ └── Vector.tt ├── Transform2d.cs ├── Transform3d.cs ├── Utilities.cs ├── Vector2d.cs ├── Vector2i.cs ├── Vector3d.cs ├── Vector3f.cs ├── Vector3i.cs └── Vector4d.cs ├── Dynamics ├── Body.cs ├── BodyPosition.cs ├── BodyRotation.cs ├── ConstraintSolver.cs ├── ConstraintSolverSettings.cs ├── Constraints │ ├── AbovePlane.cs │ ├── AlignPair.cs │ ├── Angle.cs │ ├── Cocircular.cs │ ├── Coincident.cs │ ├── Colinear.cs │ ├── Constraint.cs │ ├── Coplanar.cs │ ├── Cospherical.cs │ ├── CyclicQuad.cs │ ├── DihedralAngle.cs │ ├── Distance.cs │ ├── EqualizeLengths.cs │ ├── InsideBounds.cs │ ├── LaplacianSmooth.cs │ ├── MinimizeArea.cs │ ├── MinimizeDistance.cs │ ├── OnCircle.cs │ ├── OnCurve.cs │ ├── OnExtendedMesh.cs │ ├── OnExtendedSurface.cs │ ├── OnLine.cs │ ├── OnMesh.cs │ ├── OnPlane.cs │ ├── OnPosition.cs │ ├── OnRotation.cs │ ├── OnSphere.cs │ ├── OnSurface.cs │ ├── OnTarget.cs │ ├── OutsideSphere.cs │ ├── PlanarQuad.cs │ ├── PositionGroup.cs │ ├── PositionPair.cs │ ├── RelativePosition.cs │ ├── RelativeRotation.cs │ ├── TangentialQuad.cs │ ├── TangentialSmooth.cs │ ├── Translation.cs │ └── Trapezoid.cs ├── Extensions │ └── IEnumerableExtensions.cs ├── Forces │ ├── AreaWeight.cs │ ├── FalseWeight.cs │ ├── Force.cs │ ├── ForceField.cs │ ├── LinearWeight.cs │ ├── PositionGroup.cs │ ├── Pressure.cs │ ├── SphereCollide.cs │ └── Weight.cs └── Interfaces │ └── IConstraint.cs ├── Fields ├── Derived │ ├── GridField2dDouble.cs │ ├── GridField2dVector2d.cs │ ├── GridField2dVector3d.cs │ ├── GridField3dDouble.cs │ ├── GridField3dMatrix3d.cs │ ├── GridField3dVector3d.cs │ ├── IDWField3dDouble.cs │ ├── IDWField3dVector3d.cs │ ├── MeshField3dDouble.cs │ └── MeshField3dVector3d.cs ├── DistanceFunctions.cs ├── DistanceTransform.cs ├── Enums │ ├── IntegrationMode.cs │ ├── SampleMode.cs │ └── WrapMode.cs ├── Extensions │ ├── GridField2dExtensions.cs │ ├── GridField3dExtensions.cs │ ├── GridField3dFactoryExtensions.cs │ ├── ISampledField2dExtensions.cs │ ├── ISampledField3dExtensions.cs │ ├── ISampledFieldExtensions.cs │ ├── ListExtensions.cs │ └── MeshFieldExtensions.cs ├── Field2d.cs ├── Field3d.cs ├── Filter.cs ├── FuncField2d.cs ├── FuncField3d.cs ├── GeodesicDistance.cs ├── Grid.cs ├── Grid2d.cs ├── Grid3d.cs ├── GridField2d.cs ├── GridField2dFactory.cs ├── GridField3d.cs ├── GridField3dFactory.cs ├── GridPoint2d.cs ├── GridPoint3d.cs ├── IDWConstant3d.cs ├── IDWField3d.cs ├── IDWFieldFactory.cs ├── IDWMesh3d.cs ├── IDWObject3d.cs ├── IDWPoint3d.cs ├── ImplicitSurfaces.cs ├── Interfaces │ ├── IField2d.cs │ ├── IField3d.cs │ ├── IGradient2d.cs │ ├── IGradient3d.cs │ ├── ISampledField.cs │ ├── ISampledField2d.cs │ └── ISampledField3d.cs ├── Interop.cs ├── MeshField3d.cs ├── MeshField3dFactory.cs ├── Noise.cs ├── PerlinNoise2d.cs ├── PerlinNoise3d.cs ├── SimplexNoise2d.cs ├── SimplexNoise3d.cs └── Streamline.cs ├── Meshes ├── Delegates.cs ├── EdgeListView.cs ├── Enums │ └── SmoothBoundaryType.cs ├── Extensions │ ├── FaceExtensions.cs │ ├── HalfedgeExtensions.cs │ ├── HeStructureExtensions.cs │ └── VertexExtensions.cs ├── FaceQuadrangulator.cs ├── FaceTriangulator.cs ├── GraphSearch.cs ├── HalfedgeList.cs ├── HeGraph.cs ├── HeGraph3d.cs ├── HeGraph3dFactory.cs ├── HeGraphFactory.cs ├── HeMesh.cs ├── HeMesh3d.cs ├── HeMesh3dFactory.cs ├── HeMeshFactory.cs ├── HeMeshUnroller.cs ├── Impl │ ├── Halfedge.cs │ ├── HeGraph.cs │ ├── HeGraphFactory.cs │ ├── HeMesh.cs │ ├── HeMeshFactory.cs │ ├── HeStructure.cs │ └── Node.cs ├── Interfaces │ ├── IFaceQuadrangulator.cs │ ├── IFaceTriangulator.cs │ ├── INormal3d.cs │ └── IPosition3d.cs ├── Interop.cs ├── Matrix.cs ├── NodeList.cs ├── QuadStrip.cs ├── Selection.cs ├── Subdivision.cs ├── TriMesh.cs ├── TriMesh3d.cs └── TriMesh3f.cs ├── Properties └── AssemblyInfo.cs ├── Rhino ├── Conversions.cs ├── Extensions │ ├── ArrayViewExtensions.cs │ ├── BoundingBoxExtensions.cs │ ├── GridField2dExtensions.cs │ ├── GridField3dExtensions.cs │ ├── HeGraphFactoryExtensions.cs │ ├── HeMeshExtensions.cs │ ├── HeMeshFactoryExtensions.cs │ ├── HeNodeExtensions.cs │ ├── HeStructureExtensions.cs │ ├── IEnumerableExtensions.cs │ ├── ISampledField3dExtensions.cs │ ├── Interval2dExtensions.cs │ ├── Interval3dExtensions.cs │ ├── LineExtensions.cs │ ├── MeshExtensions.cs │ ├── Orient3dExtensions.cs │ ├── PlaneExtensions.cs │ ├── Point3dExtensions.cs │ ├── PriorityQueueExtensions.cs │ ├── QuadStripExtensions.cs │ ├── TransformExtensions.cs │ └── Vector3dExtensions.cs ├── Field3d.cs ├── Isosurface.cs └── RhinoFactory.cs ├── SpatialSlur.csproj ├── Tools ├── DynamicRemesher.cs ├── Features │ ├── CurveFeature.cs │ ├── ExtendedMeshFeature.cs │ ├── IFeature.cs │ ├── ISurfaceFeature.cs │ ├── MeshFeature.cs │ ├── PointCloudFeature.cs │ └── PointFeature.cs ├── LoopGrower.cs └── SteinerFinder.cs ├── Unity ├── Conversions.cs └── Extensions │ ├── ArrayExtensions.cs │ ├── IReadOnlyListExtensions.cs │ └── Matrix4x4Extensions.cs └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Examples/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Examples/Gallery/170720_Relief_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Gallery/170720_Relief_02.gif -------------------------------------------------------------------------------- /Examples/Gallery/h_01_3_zoom_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Gallery/h_01_3_zoom_2.png -------------------------------------------------------------------------------- /Examples/Grasshopper/Distance_Transform.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Distance_Transform.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Dynamic_Remesher.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Dynamic_Remesher.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/Dynamic_Remesher.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Dynamic_Remesher.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Funicular_Network.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Funicular_Network.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/Funicular_Network.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Funicular_Network.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Geodesic_Field.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Geodesic_Field.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/Geodesic_Field.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Geodesic_Field.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Geodesic_Field_3d.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Geodesic_Field_3d.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/Geodesic_Field_3d.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Geodesic_Field_3d.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/HeMesh_Unroll.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/HeMesh_Unroll.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/IDWField_Example.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/IDWField_Example.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/IDWField_Example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/IDWField_Example.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Noise_Field_Integration.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Noise_Field_Integration.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Quad_Strips.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Quad_Strips.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Sort_Faces_By_Depth.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Sort_Faces_By_Depth.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/SphereCollide.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/SphereCollide.3dm -------------------------------------------------------------------------------- /Examples/Grasshopper/Sphere_Collide.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Sphere_Collide.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/Steiner_Tree_Finder.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Steiner_Tree_Finder.gh -------------------------------------------------------------------------------- /Examples/Grasshopper/User Objects/SlurCS.ghuser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/User Objects/SlurCS.ghuser -------------------------------------------------------------------------------- /Examples/Grasshopper/Volumetric_Clustering.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Grasshopper/Volumetric_Clustering.gh -------------------------------------------------------------------------------- /Examples/HeMeshFromFile.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur.Fields; 8 | using SpatialSlur.Meshes; 9 | 10 | namespace SpatialSlur.Examples 11 | { 12 | /// 13 | /// 14 | /// 15 | static class HeMeshFromFile 16 | { 17 | const string _fileIn = "face_0.obj"; 18 | const string _fileOut = "face_mapped_0.obj"; 19 | 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static void Start() 26 | { 27 | var mesh = HeMesh3d.Factory.CreateFromOBJ(Paths.Resources + _fileIn); 28 | var verts = mesh.Vertices; 29 | 30 | var texCoords = new Vector2d[verts.Count]; 31 | double scale = 0.5; 32 | double offset = scale * Math.PI * 0.25; 33 | 34 | // create texture coordinates from implicit function 35 | for (int i = 0; i < verts.Count; i++) 36 | { 37 | var p = verts[i].Position * scale; 38 | var u = ImplicitSurfaces.Gyroid(p.X, p.Y, p.Z); 39 | var v = ImplicitSurfaces.Gyroid(p.X + offset, p.Y + offset, p.Z + offset); 40 | texCoords[i] = new Vector2d(u, v); 41 | } 42 | 43 | // compute vertex normals & write to file 44 | mesh.Vertices.Action(v => v.Normal = v.GetNormal(), true); 45 | Interop.Meshes.WriteToObj(mesh, Paths.Resources + _fileOut, v => texCoords[v]); 46 | 47 | Console.WriteLine("File written successfully. Press return to exit."); 48 | Console.ReadLine(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Examples/Paths.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | namespace SpatialSlur.Examples 6 | { 7 | /// 8 | /// 9 | /// 10 | static class Paths 11 | { 12 | public const string Resources = @"../../Resources/"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/PlanarizeHeMesh.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | using SpatialSlur; 9 | using SpatialSlur.Meshes; 10 | using SpatialSlur.Dynamics; 11 | using SpatialSlur.Dynamics.Constraints; 12 | 13 | namespace SpatialSlur.Examples 14 | { 15 | /// 16 | /// 17 | /// 18 | static class PlanarizeHeMesh 19 | { 20 | const string _fileIn = "chair_smooth_0.obj"; 21 | const string _fileOut = "chair_planar_0.obj"; 22 | 23 | 24 | /// 25 | /// 26 | /// 27 | public static void Start() 28 | { 29 | // import halfedge mesh 30 | var mesh = HeMesh3d.Factory.CreateFromOBJ(Paths.Resources + _fileIn); 31 | 32 | // create particles 33 | var bodies = mesh.Vertices.Select(v => new Body(v.Position)).ToArray(); 34 | 35 | // create constraints 36 | var constraints = mesh.Faces.Where(f => !f.IsDegree3) 37 | .Select(f => new Coplanar(f.Vertices.Select(v => v.Index))) 38 | .ToArray(); 39 | 40 | // create solver 41 | var solver = new ConstraintSolver(); 42 | solver.Settings.LinearDamping = 0.1; 43 | 44 | // wait for keypress to start the solver 45 | Console.WriteLine("Press return to start the solver."); 46 | Console.ReadLine(); 47 | 48 | // step the solver until converged 49 | while (!solver.IsConverged) 50 | { 51 | solver.Step(bodies, constraints, true); 52 | Console.WriteLine($" step {solver.StepCount}"); 53 | } 54 | Console.WriteLine("\nSolver converged! Press return to exit."); 55 | 56 | // update mesh vertices 57 | mesh.Vertices.Action(v => v.Position = bodies[v].Position.Current); // mesh elements (vertices, halfedges, faces) are implicitly converted to their index 58 | 59 | // compute vertex normals & write to file 60 | mesh.Vertices.Action(v => v.Normal = v.GetNormal(), true); 61 | Interop.Meshes.WriteToObj(mesh, Paths.Resources + _fileOut); 62 | Console.ReadLine(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Examples/PlanarizeQuad.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur; 8 | using SpatialSlur.Dynamics; 9 | using SpatialSlur.Dynamics.Constraints; 10 | 11 | namespace SpatialSlur.Examples 12 | { 13 | /// 14 | /// Planarizes a randomly generated quadrilateral. 15 | /// 16 | static class PlanarizeQuad 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | public static void Start() 23 | { 24 | var random = new Random(0); 25 | var box = new Interval3d(new Vector3d(0.0), new Vector3d(10.0)); // create a interval between the (0,0,0) and (10,10,10) 26 | 27 | // create bodies 28 | var bodies = new Body[] { 29 | new Body(random.NextVector3d(box)), 30 | new Body(random.NextVector3d(box)), 31 | new Body(random.NextVector3d(box)), 32 | new Body(random.NextVector3d(box)) 33 | }; 34 | 35 | // create constraints 36 | var constraints = new IConstraint[] { 37 | new PlanarQuad(0, 1, 2, 3) 38 | }; 39 | 40 | // create solver 41 | var solver = new ConstraintSolver(); 42 | 43 | // wait for keypress to start the solver 44 | Console.WriteLine("Press return to start the solver."); 45 | Console.ReadLine(); 46 | 47 | // step the solver until converged 48 | while (!solver.IsConverged) 49 | { 50 | solver.Step(bodies, constraints); 51 | Console.WriteLine($" step {solver.StepCount}"); 52 | } 53 | 54 | Console.WriteLine("\nSolver converged! Press return to exit."); 55 | Console.ReadLine(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Examples/Program.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Linq; 7 | using System.Collections.Generic; 8 | 9 | namespace SpatialSlur.Examples 10 | { 11 | /// 12 | /// 13 | /// 14 | static class Program 15 | { 16 | /// 17 | /// 18 | /// 19 | public static void Main() 20 | { 21 | PlanarizeHeMesh.Start(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Examples")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Examples")] 12 | [assembly: AssemblyCopyright("Copyright © David Reeves 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("2bcae614-c7c3-4359-9701-3a1f7dd4c85f")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion(SpatialSlur.AssemblyInfo.VersionNumber)] 35 | -------------------------------------------------------------------------------- /Examples/Resources/Images/Geoff-McFetridge-Hands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davreev/SpatialSlur/8c14b0c40cf102fa51f28091a2d6f213c56aba97/Examples/Resources/Images/Geoff-McFetridge-Hands.png -------------------------------------------------------------------------------- /Examples/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014 David Reeves 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /SlurGH/Components/Display/DisplayFaceColors.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | 10 | using Grasshopper.Kernel; 11 | using Grasshopper.Kernel.Types; 12 | 13 | using SpatialSlur.Meshes; 14 | using SpatialSlur.Rhino; 15 | using SpatialSlur.Grasshopper.Params; 16 | 17 | namespace SpatialSlur.Grasshopper.Components 18 | { 19 | /// 20 | /// 21 | /// 22 | public class DisplayFaceColors : GH_Component 23 | { 24 | /// 25 | /// 26 | /// 27 | public DisplayFaceColors() 28 | : base("Display Face Colors", "FaceCol", 29 | "Applies a solid color to each face in a halfedge mesh.", 30 | "SpatialSlur", "Display") 31 | { 32 | } 33 | 34 | 35 | /// 36 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 37 | { 38 | pManager.AddParameter(new HeMesh3dParam(), "heMesh", "heMesh", "Mesh to color", GH_ParamAccess.item); 39 | pManager.AddColourParameter("colors", "colors", "", GH_ParamAccess.list); 40 | } 41 | 42 | 43 | /// 44 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 45 | { 46 | pManager.AddMeshParameter("mesh", "mesh", "Colored mesh", GH_ParamAccess.item); 47 | } 48 | 49 | 50 | /// 51 | protected override void SolveInstance(IGH_DataAccess DA) 52 | { 53 | HeMesh3d mesh = null; 54 | List colors = new List(); 55 | 56 | if (!DA.GetData(0, ref mesh)) return; 57 | if (!DA.GetDataList(1, colors)) return; 58 | 59 | int last = colors.Count - 1; 60 | var result = mesh.ToPolySoup(f => colors[Math.Min(f, last)]); 61 | 62 | DA.SetData(0, new GH_Mesh(result)); 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{65C6B961-F1D1-4C41-87C9-C43FB3778923}"); } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /SlurGH/Components/Enums/DistanceMetrics.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace SpatialSlur.Grasshopper.Components 13 | { 14 | /// 15 | /// 16 | /// 17 | public enum DistanceMetric 18 | { 19 | /// 20 | Manhattan, 21 | /// 22 | Euclidean, 23 | /// 24 | Chebyshev 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SlurGH/Components/Enums/FieldType.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | namespace SpatialSlur.Grasshopper.Components 6 | { 7 | /// 8 | /// 9 | /// 10 | public enum FieldType 11 | { 12 | Scalar, 13 | Vector 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SlurGH/Components/Enums/NoiseType.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | namespace SpatialSlur.Grasshopper.Components 6 | { 7 | /// 8 | /// 9 | /// 10 | public enum NoiseType 11 | { 12 | Perlin, 13 | Simplex 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SlurGH/Components/Enums/SimState.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | namespace SpatialSlur.Grasshopper.Components 6 | { 7 | /// 8 | /// 9 | /// 10 | public enum SimState 11 | { 12 | Play, 13 | Pause, 14 | Reset 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/AlignVertices.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using Grasshopper.Kernel; 10 | using Grasshopper.Kernel.Types; 11 | using Rhino.Geometry; 12 | 13 | using SpatialSlur; 14 | using SpatialSlur.Collections; 15 | 16 | using Vec3d = Rhino.Geometry.Vector3d; 17 | 18 | namespace SpatialSlur.Grasshopper.Components 19 | { 20 | /// 21 | /// 22 | /// 23 | public class AlignVertices : GH_Component 24 | { 25 | /// 26 | /// 27 | /// 28 | public AlignVertices() 29 | : base("Align Vertices", "AlignVerts", 30 | "Aligns positions of near-coincident vertices in a mesh.", 31 | "Mesh", "Util") 32 | { 33 | } 34 | 35 | 36 | /// 37 | protected override void RegisterInputParams(GH_InputParamManager pManager) 38 | { 39 | pManager.AddMeshParameter("mesh", "mesh", "Mesh with vertices to align", GH_ParamAccess.item); 40 | pManager.AddNumberParameter("radius", "radius", "Vertex search radius", GH_ParamAccess.item, 1.0e-4); 41 | } 42 | 43 | 44 | /// 45 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 46 | { 47 | pManager.AddMeshParameter("result", "result", "Mesh with aligned vertices", GH_ParamAccess.item); 48 | } 49 | 50 | 51 | /// 52 | protected override void SolveInstance(IGH_DataAccess DA) 53 | { 54 | Mesh mesh = null; 55 | double tol = 0.0; 56 | 57 | if (!DA.GetData(0, ref mesh)) return; 58 | if (!DA.GetData(1, ref tol)) return; 59 | 60 | var verts = mesh.Vertices; 61 | var points = verts.Select(p => (Vector3d)p).ToArray(); 62 | 63 | Proximity.Consolidate(points, tol, 3); 64 | //Message = (points.Consolidate(tol)) ? "Converged" : "Not converged"; 65 | 66 | for (int i = 0; i < verts.Count; i++) 67 | verts[i] = (Point3f)points[i]; 68 | 69 | DA.SetData(0, new GH_Mesh(mesh)); 70 | } 71 | 72 | 73 | /// 74 | /// Provides an Icon for every component that will be visible in the User Interface. 75 | /// Icons need to be 24x24 pixels. 76 | /// 77 | protected override System.Drawing.Bitmap Icon 78 | { 79 | get { return null; } 80 | } 81 | 82 | 83 | /// 84 | /// Each component must have a unique Guid to identify it. 85 | /// It is vital this Guid doesn't change otherwise old ghx files 86 | /// that use the old ID will partially fail during loading. 87 | /// 88 | public override Guid ComponentGuid 89 | { 90 | get { return new Guid("{FC8A6CF2-C16A-4A23-8012-28B9F36B1844}"); } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/MeshClosedPolyline.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using Grasshopper.Kernel; 8 | using Grasshopper.Kernel.Types; 9 | using Rhino.Geometry; 10 | 11 | using Vec3d = Rhino.Geometry.Vector3d; 12 | 13 | namespace SpatialSlur.Grasshopper.Components 14 | { 15 | /// 16 | /// 17 | /// 18 | public class MeshClosedPolyline : GH_Component 19 | { 20 | /// 21 | /// 22 | /// 23 | public MeshClosedPolyline() 24 | : base("Mesh Closed Polyline", "MeshPoly", 25 | "Creates a mesh from a closed polyline.", 26 | "Mesh", "Util") 27 | { 28 | } 29 | 30 | 31 | /// 32 | protected override void RegisterInputParams(GH_InputParamManager pManager) 33 | { 34 | pManager.AddCurveParameter("polyline", "poly", "Closed polyline to mesh", GH_ParamAccess.item); 35 | } 36 | 37 | 38 | /// 39 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 40 | { 41 | pManager.AddMeshParameter("mesh", "mesh", "Resulting mesh", GH_ParamAccess.item); 42 | } 43 | 44 | 45 | /// 46 | protected override void SolveInstance(IGH_DataAccess DA) 47 | { 48 | GH_Curve curve = null; 49 | if (!DA.GetData(0, ref curve)) return; 50 | 51 | if (!curve.Value.TryGetPolyline(out var poly)) 52 | throw new ArgumentException("The given curve is not a polyline."); 53 | 54 | DA.SetData(0, new GH_Mesh(Mesh.CreateFromClosedPolyline(poly))); 55 | } 56 | 57 | 58 | /// 59 | /// Provides an Icon for every component that will be visible in the User Interface. 60 | /// Icons need to be 24x24 pixels. 61 | /// 62 | protected override System.Drawing.Bitmap Icon 63 | { 64 | get { return null; } 65 | } 66 | 67 | 68 | /// 69 | /// Each component must have a unique Guid to identify it. 70 | /// It is vital this Guid doesn't change otherwise old ghx files 71 | /// that use the old ID will partially fail during loading. 72 | /// 73 | public override Guid ComponentGuid 74 | { 75 | get { return new Guid("{8D35230C-B9CD-479D-AAD6-F579E4BEB5F1}"); } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/MeshExtrude.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using Rhino.Geometry; 8 | using Grasshopper.Kernel; 9 | using Grasshopper.Kernel.Types; 10 | using SpatialSlur.Rhino; 11 | 12 | using Vec3d = Rhino.Geometry.Vector3d; 13 | 14 | namespace SpatialSlur.Grasshopper.Components 15 | { 16 | /// 17 | /// 18 | /// 19 | public class MeshExtrude : GH_Component 20 | { 21 | /// 22 | /// 23 | /// 24 | public MeshExtrude() 25 | : base("Mesh Extrude", "Extrude", 26 | "Extrudes a mesh from a polyline", 27 | "Mesh", "Util") 28 | { 29 | } 30 | 31 | 32 | /// 33 | protected override void RegisterInputParams(GH_InputParamManager pManager) 34 | { 35 | pManager.AddCurveParameter("polyline", "poly", "", GH_ParamAccess.item); 36 | pManager.AddVectorParameter("direction", "dir", "", GH_ParamAccess.item, Vec3d.Zero); 37 | } 38 | 39 | 40 | /// 41 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 42 | { 43 | pManager.AddMeshParameter("result", "result", "Extruded mesh", GH_ParamAccess.item); 44 | } 45 | 46 | 47 | /// 48 | protected override void SolveInstance(IGH_DataAccess DA) 49 | { 50 | Curve crv = null; 51 | var dir = new Vec3d(); 52 | 53 | if (!DA.GetData(0, ref crv)) return; 54 | if (!DA.GetData(1, ref dir)) return; 55 | 56 | Polyline poly; 57 | 58 | if (!crv.TryGetPolyline(out poly)) 59 | throw new ArgumentException(); 60 | 61 | var mesh = RhinoFactory.Mesh.CreateExtrusion(poly, dir); 62 | DA.SetData(0, new GH_Mesh(mesh)); 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{7A0D856D-7C43-42D1-AEEC-BACDDA1881A4}"); } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/MeshLoft.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using Rhino.Geometry; 9 | using Grasshopper.Kernel; 10 | using Grasshopper.Kernel.Types; 11 | using SpatialSlur.Rhino; 12 | 13 | namespace SpatialSlur.Grasshopper.Components 14 | { 15 | /// 16 | /// 17 | /// 18 | public class MeshLoft : GH_Component 19 | { 20 | /// 21 | /// 22 | /// 23 | public MeshLoft() 24 | : base("Mesh Loft", "Loft", 25 | "Creates a mesh through a list of polylines", 26 | "Mesh", "Util") 27 | { 28 | } 29 | 30 | 31 | /// 32 | protected override void RegisterInputParams(GH_InputParamManager pManager) 33 | { 34 | pManager.AddCurveParameter("polylines", "polys", "", GH_ParamAccess.list); 35 | } 36 | 37 | 38 | /// 39 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 40 | { 41 | pManager.AddMeshParameter("result", "result", "Lofted mesh", GH_ParamAccess.item); 42 | } 43 | 44 | 45 | /// 46 | protected override void SolveInstance(IGH_DataAccess DA) 47 | { 48 | List curves = new List(); 49 | 50 | if (!DA.GetDataList(0, curves)) return; 51 | 52 | var polys = curves.ConvertAll(crv => 53 | { 54 | if (!crv.TryGetPolyline(out Polyline poly)) 55 | throw new ArgumentException(); 56 | 57 | return poly; 58 | }); 59 | 60 | var mesh = RhinoFactory.Mesh.CreateLoft(polys); 61 | 62 | DA.SetData(0, new GH_Mesh(mesh)); 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{BCFCF1AE-046B-4164-AF5A-12E5EE9F71CD}"); } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/MeshLoftPair.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using Grasshopper.Kernel; 8 | using Grasshopper.Kernel.Types; 9 | using Rhino.Geometry; 10 | using SpatialSlur.Rhino; 11 | 12 | namespace SpatialSlur.Grasshopper.Components 13 | { 14 | /// 15 | /// 16 | /// 17 | public class MeshLoftPair : GH_Component 18 | { 19 | /// 20 | /// 21 | /// 22 | public MeshLoftPair() 23 | : base("Mesh Loft Pair", "LoftPair", 24 | "Creates a mesh between a pair of polylines", 25 | "Mesh", "Util") 26 | { 27 | } 28 | 29 | 30 | /// 31 | protected override void RegisterInputParams(GH_InputParamManager pManager) 32 | { 33 | pManager.AddCurveParameter("polylineA", "polyA", "", GH_ParamAccess.item); 34 | pManager.AddCurveParameter("polylineB", "polyB", "", GH_ParamAccess.item); 35 | } 36 | 37 | 38 | /// 39 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 40 | { 41 | pManager.AddMeshParameter("result", "result", "Lofted mesh", GH_ParamAccess.item); 42 | } 43 | 44 | 45 | /// 46 | protected override void SolveInstance(IGH_DataAccess DA) 47 | { 48 | Curve crvA = null; 49 | Curve crvB = null; 50 | 51 | if (!DA.GetData(0, ref crvA)) return; 52 | if (!DA.GetData(1, ref crvB)) return; 53 | 54 | if (!crvA.TryGetPolyline(out Polyline polyA)) 55 | throw new ArgumentException(); 56 | 57 | if (!crvB.TryGetPolyline(out Polyline polyB)) 58 | throw new ArgumentException(); 59 | 60 | var mesh = RhinoFactory.Mesh.CreateLoft(polyA, polyB); 61 | 62 | DA.SetData(0, new GH_Mesh(mesh)); 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{C8AA832B-3A0C-4CF8-A63A-65414619BDF8}"); } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /SlurGH/Components/Mesh/MeshSeparate.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using Rhino.Geometry; 8 | using Grasshopper.Kernel; 9 | using Grasshopper.Kernel.Types; 10 | using SpatialSlur.Rhino; 11 | 12 | namespace SpatialSlur.Grasshopper.Components 13 | { 14 | /// 15 | /// 16 | /// 17 | public class MeshSeparate : GH_Component 18 | { 19 | /// 20 | /// 21 | /// 22 | public MeshSeparate() 23 | : base("Mesh Separate", "Separate", 24 | "Separates all faces in a given mesh", 25 | "Mesh", "Util") 26 | { 27 | } 28 | 29 | 30 | /// 31 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 32 | { 33 | pManager.AddMeshParameter("mesh", "mesh", "Mesh to separate", GH_ParamAccess.item); 34 | } 35 | 36 | 37 | /// 38 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 39 | { 40 | pManager.AddMeshParameter("result", "result", "Separated mesh", GH_ParamAccess.item); 41 | } 42 | 43 | 44 | /// 45 | protected override void SolveInstance(IGH_DataAccess DA) 46 | { 47 | Mesh mesh = null; 48 | if (!DA.GetData(0, ref mesh)) return; 49 | 50 | mesh = mesh.ToPolySoup(); 51 | 52 | DA.SetData(0, new GH_Mesh(mesh)); 53 | } 54 | 55 | 56 | /// 57 | /// Provides an Icon for every component that will be visible in the User Interface. 58 | /// Icons need to be 24x24 pixels. 59 | /// 60 | protected override System.Drawing.Bitmap Icon 61 | { 62 | get { return null; } 63 | } 64 | 65 | 66 | /// 67 | /// Each component must have a unique Guid to identify it. 68 | /// It is vital this Guid doesn't change otherwise old ghx files 69 | /// that use the old ID will partially fail during loading. 70 | /// 71 | public override Guid ComponentGuid 72 | { 73 | get { return new Guid("{29FE6C46-B4B0-4BEE-95D6-549001490DE5}"); } 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Meshes/FacePlanarity.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using Grasshopper.Kernel; 10 | 11 | using SpatialSlur.Meshes; 12 | using SpatialSlur.Grasshopper.Types; 13 | using SpatialSlur.Grasshopper.Params; 14 | 15 | namespace SlurGH.Components 16 | { 17 | /// 18 | /// 19 | /// 20 | public class FacePlanarity : GH_Component 21 | { 22 | /// 23 | /// 24 | /// 25 | public FacePlanarity() 26 | : base("Face Planarity", "FacePln", 27 | "Returns the planar deviation of each face in a halfedge mesh.", 28 | "SpatialSlur", "Mesh") 29 | { 30 | } 31 | 32 | 33 | /// 34 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 35 | { 36 | pManager.AddParameter(new HeMesh3dParam(), "heMesh", "heMesh", "", GH_ParamAccess.item); 37 | } 38 | 39 | 40 | /// 41 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 42 | { 43 | pManager.AddNumberParameter("result", "result", "", GH_ParamAccess.list); 44 | } 45 | 46 | 47 | /// 48 | protected override void SolveInstance(IGH_DataAccess DA) 49 | { 50 | GH_HeMesh3d mesh = null; 51 | if (!DA.GetData(0, ref mesh)) return; 52 | 53 | var result = mesh.Value.Faces.Select(f => f.IsUnused ? 0.0 : f.GetPlanarity(v => v.Position)); 54 | DA.SetDataList(0, result); 55 | } 56 | 57 | 58 | /// 59 | /// Provides an Icon for every component that will be visible in the User Interface. 60 | /// Icons need to be 24x24 pixels. 61 | /// 62 | protected override System.Drawing.Bitmap Icon 63 | { 64 | get { return null; } 65 | } 66 | 67 | 68 | /// 69 | /// Each component must have a unique Guid to identify it. 70 | /// It is vital this Guid doesn't change otherwise old ghx files 71 | /// that use the old ID will partially fail during loading. 72 | /// 73 | public override Guid ComponentGuid 74 | { 75 | get { return new Guid("{85A0F167-8DCD-4397-848F-93482E6708D7}"); } 76 | } 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Meshes/FacePolylines.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using Grasshopper.Kernel; 10 | using Grasshopper.Kernel.Types; 11 | using Rhino.Geometry; 12 | 13 | using SpatialSlur.Grasshopper.Types; 14 | using SpatialSlur.Grasshopper.Params; 15 | 16 | namespace SlurGH.Components 17 | { 18 | /// 19 | /// 20 | /// 21 | public class FacePolylines : GH_Component 22 | { 23 | /// 24 | /// 25 | /// 26 | public FacePolylines() 27 | : base("Face Polylines", "FacePolys", 28 | "Returns the boundary of each face in a given halfedge mesh as a closed polyline", 29 | "SpatialSlur", "Mesh") 30 | { 31 | } 32 | 33 | 34 | /// 35 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 36 | { 37 | pManager.AddParameter(new HeMesh3dParam(), "heMesh", "heMesh", "", GH_ParamAccess.item); 38 | } 39 | 40 | 41 | /// 42 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 43 | { 44 | pManager.AddCurveParameter("result", "result", "", GH_ParamAccess.list); 45 | } 46 | 47 | 48 | /// 49 | protected override void SolveInstance(IGH_DataAccess DA) 50 | { 51 | GH_HeMesh3d mesh = null; 52 | if (!DA.GetData(0, ref mesh)) return; 53 | 54 | var result = mesh.Value.Faces.Select(f => 55 | { 56 | if (f.IsUnused) return new GH_Curve(); 57 | 58 | var poly = new Polyline(f.Halfedges.Select(he => (Point3d)he.Start.Position)); 59 | poly.Add(poly[0]); 60 | 61 | return new GH_Curve(poly.ToNurbsCurve()); 62 | }); 63 | 64 | DA.SetDataList(0, result); 65 | } 66 | 67 | 68 | /// 69 | /// Provides an Icon for every component that will be visible in the User Interface. 70 | /// Icons need to be 24x24 pixels. 71 | /// 72 | protected override System.Drawing.Bitmap Icon 73 | { 74 | get { return null; } 75 | } 76 | 77 | 78 | /// 79 | /// Each component must have a unique Guid to identify it. 80 | /// It is vital this Guid doesn't change otherwise old ghx files 81 | /// that use the old ID will partially fail during loading. 82 | /// 83 | public override Guid ComponentGuid 84 | { 85 | get { return new Guid("{BD140500-B9EA-43EE-94B9-358BEACF803C}"); } 86 | } 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Meshes/HeMeshFromPolylines.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | using Rhino.Geometry; 11 | using Grasshopper.Kernel; 12 | using Grasshopper.Kernel.Types; 13 | 14 | using SpatialSlur.Meshes; 15 | using SpatialSlur.Rhino; 16 | using SpatialSlur.Grasshopper.Types; 17 | using SpatialSlur.Grasshopper.Params; 18 | 19 | namespace SpatialSlur.Grasshopper.Components 20 | { 21 | /// 22 | /// 23 | /// 24 | public class HeMeshFromPolylines : GH_Component 25 | { 26 | /// 27 | /// 28 | /// 29 | public HeMeshFromPolylines() 30 | : base("HeMesh From Polylines", "FromPolys", 31 | "Creates a halfedge mesh from a list of closed polylines", 32 | "SpatialSlur", "Mesh") 33 | { 34 | } 35 | 36 | 37 | /// 38 | protected override void RegisterInputParams(GH_InputParamManager pManager) 39 | { 40 | pManager.AddCurveParameter("polylines", "polys", "", GH_ParamAccess.list); 41 | pManager.AddNumberParameter("tolerance", "tol", "", GH_ParamAccess.item, 1.0e-4); 42 | } 43 | 44 | 45 | /// 46 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 47 | { 48 | pManager.AddParameter(new HeMesh3dParam(), "result", "result", "", GH_ParamAccess.item); 49 | } 50 | 51 | 52 | /// 53 | protected override void SolveInstance(IGH_DataAccess DA) 54 | { 55 | var curves = new List(); 56 | if (!DA.GetDataList(0, curves)) return; 57 | 58 | var tol = 0.0; 59 | if (!DA.GetData(1, ref tol)) return; 60 | 61 | var mesh = HeMesh3d.Factory.CreateFromPolylines(curves.Select(crv => 62 | { 63 | crv.Value.TryGetPolyline(out Polyline poly); 64 | return poly; 65 | }), tol); 66 | 67 | DA.SetData(0, new GH_HeMesh3d(mesh)); 68 | } 69 | 70 | 71 | /// 72 | /// Provides an Icon for every component that will be visible in the User Interface. 73 | /// Icons need to be 24x24 pixels. 74 | /// 75 | protected override System.Drawing.Bitmap Icon 76 | { 77 | get { return null; } 78 | } 79 | 80 | 81 | /// 82 | /// Each component must have a unique Guid to identify it. 83 | /// It is vital this Guid doesn't change otherwise old ghx files 84 | /// that use the old ID will partially fail during loading. 85 | /// 86 | public override Guid ComponentGuid 87 | { 88 | get { return new Guid("{2A36DB93-46BB-419C-810B-98B67D88BEDB}"); } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Meshes/HoleBoundaries.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using Grasshopper.Kernel; 10 | using Grasshopper.Kernel.Types; 11 | using Rhino.Geometry; 12 | 13 | using SpatialSlur.Grasshopper.Types; 14 | using SpatialSlur.Grasshopper.Params; 15 | 16 | namespace SlurGH.Components 17 | { 18 | /// 19 | /// 20 | /// 21 | public class HoleBoundaries : GH_Component 22 | { 23 | /// 24 | /// 25 | /// 26 | public HoleBoundaries() 27 | : base("Hole Boundaries", "HoleBnds", 28 | "Returns the boundary of each hole in a given halfedge mesh as a closed polyline", 29 | "SpatialSlur", "Mesh") 30 | { 31 | } 32 | 33 | 34 | /// 35 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 36 | { 37 | pManager.AddParameter(new HeMesh3dParam(), "heMesh", "heMesh", "Halfedge structure to extract from", GH_ParamAccess.item); 38 | } 39 | 40 | 41 | /// 42 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 43 | { 44 | pManager.AddCurveParameter("result", "result", "Face polylines", GH_ParamAccess.list); 45 | } 46 | 47 | 48 | /// 49 | protected override void SolveInstance(IGH_DataAccess DA) 50 | { 51 | GH_HeMesh3d mesh = null; 52 | if (!DA.GetData(0, ref mesh)) return; 53 | 54 | var result = mesh.Value.GetHoles().Select(he0 => 55 | { 56 | var poly = new Polyline(he0.Circulate.Select(he => (Point3d)he.Start.Position)); 57 | poly.Add(poly[0]); 58 | 59 | return new GH_Curve(poly.ToNurbsCurve()); 60 | }); 61 | 62 | DA.SetDataList(0, result); 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{0B107055-DE31-467B-9762-C0F44430A2FF}"); } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Meshes/VertexPositions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using Grasshopper.Kernel; 10 | using Grasshopper.Kernel.Types; 11 | using SpatialSlur.Meshes; 12 | 13 | namespace SpatialSlur.Grasshopper.Components 14 | { 15 | /// 16 | /// 17 | /// 18 | public class VertexPositions : GH_Component 19 | { 20 | /// 21 | /// 22 | /// 23 | public VertexPositions() 24 | : base("Vertex Positions", "VertPos", 25 | "Returns the position of each vertex in a halfedge graph.", 26 | "SpatialSlur", "Mesh") 27 | { 28 | } 29 | 30 | 31 | /// 32 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 33 | { 34 | pManager.AddGenericParameter("heGraph", "heGraph", "", GH_ParamAccess.item); 35 | } 36 | 37 | 38 | /// 39 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 40 | { 41 | pManager.AddPointParameter("result", "result", "Vertex positions", GH_ParamAccess.list); 42 | } 43 | 44 | 45 | /// 46 | protected override void SolveInstance(IGH_DataAccess DA) 47 | { 48 | GH_ObjectWrapper goo = null; 49 | if (!DA.GetData(0, ref goo)) return; 50 | 51 | var obj = goo.Value; 52 | 53 | if (obj is HeGraph3d) 54 | { 55 | var graph = (HeGraph3d)obj; 56 | DA.SetDataList(0, graph.Vertices.Select(v => new GH_Point(v.Position))); 57 | } 58 | else if (obj is HeMesh3d) 59 | { 60 | var mesh = (HeMesh3d)obj; 61 | DA.SetDataList(0, mesh.Vertices.Select(v => new GH_Point(v.Position))); 62 | } 63 | } 64 | 65 | 66 | /// 67 | /// Provides an Icon for every component that will be visible in the User Interface. 68 | /// Icons need to be 24x24 pixels. 69 | /// 70 | protected override System.Drawing.Bitmap Icon 71 | { 72 | get { return null; } 73 | } 74 | 75 | 76 | /// 77 | /// Each component must have a unique Guid to identify it. 78 | /// It is vital this Guid doesn't change otherwise old ghx files 79 | /// that use the old ID will partially fail during loading. 80 | /// 81 | public override Guid ComponentGuid 82 | { 83 | get { return new Guid("{F39B5887-09E7-4D40-B0C6-CA69073936B1}"); } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /SlurGH/Components/SpatialSlur/Tools/CreateFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using Rhino.Geometry; 8 | using Grasshopper.Kernel; 9 | using Grasshopper.Kernel.Types; 10 | using SpatialSlur.Tools; 11 | 12 | namespace SpatialSlur.Grasshopper.Components 13 | { 14 | /// 15 | /// 16 | /// 17 | public class CreateFeature : GH_Component 18 | { 19 | /// 20 | /// 21 | /// 22 | public CreateFeature() 23 | : base("Creates Features", "Feature", 24 | "Creates a geometric feature used for dynamic remeshing", 25 | "SpatialSlur", "Mesh") 26 | { 27 | } 28 | 29 | 30 | /// 31 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) 32 | { 33 | pManager.AddGenericParameter("geometry", "geom", "", GH_ParamAccess.item); 34 | } 35 | 36 | 37 | /// 38 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) 39 | { 40 | pManager.AddGenericParameter("result", "result", "", GH_ParamAccess.item); 41 | } 42 | 43 | 44 | /// 45 | protected override void SolveInstance(IGH_DataAccess DA) 46 | { 47 | GH_ObjectWrapper goo = null; 48 | if (!DA.GetData(0, ref goo)) return; 49 | 50 | IFeature feat = null; 51 | 52 | switch (goo.Value) 53 | { 54 | case Mesh m: 55 | feat = new MeshFeature(m); 56 | break; 57 | case Curve c: 58 | feat = new CurveFeature(c); 59 | break; 60 | case Point3d p: 61 | feat = new PointFeature(p); 62 | break; 63 | default: 64 | throw new ArgumentException(); 65 | } 66 | 67 | DA.SetData(0, new GH_ObjectWrapper(feat)); 68 | } 69 | 70 | 71 | /// 72 | /// Provides an Icon for every component that will be visible in the User Interface. 73 | /// Icons need to be 24x24 pixels. 74 | /// 75 | protected override System.Drawing.Bitmap Icon 76 | { 77 | get { return null; } 78 | } 79 | 80 | 81 | /// 82 | /// Each component must have a unique Guid to identify it. 83 | /// It is vital this Guid doesn't change otherwise old ghx files 84 | /// that use the old ID will partially fail during loading. 85 | /// 86 | public override Guid ComponentGuid 87 | { 88 | get { return new Guid("{0FEF2BE4-6432-4352-ADE2-F160108EDA12}"); } 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /SlurGH/Params/SpatialSlur/HeGraph3dParam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using Grasshopper.Kernel; 5 | 6 | using SpatialSlur.Grasshopper.Types; 7 | 8 | /* 9 | * Notes 10 | */ 11 | 12 | namespace SpatialSlur.Grasshopper.Params 13 | { 14 | /// 15 | /// 16 | /// 17 | public class HeGraph3dParam : GH_PersistentParam 18 | { 19 | /// 20 | /// 21 | /// 22 | public HeGraph3dParam() 23 | :base("HeGraph", "HeGraph", "", "SpatialSlur", "Parameters") 24 | { 25 | } 26 | 27 | 28 | /// 29 | public override GH_Exposure Exposure 30 | { 31 | get { return GH_Exposure.primary; } 32 | } 33 | 34 | 35 | /// 36 | protected override Bitmap Icon 37 | { 38 | get { return null; } 39 | } 40 | 41 | 42 | /// 43 | public override Guid ComponentGuid 44 | { 45 | get { return new Guid("{E173CB1B-FBE2-4F71-89A2-D520C6AF6A7F}"); } 46 | } 47 | 48 | 49 | /// 50 | protected override GH_GetterResult Prompt_Singular(ref GH_HeGraph3d value) 51 | { 52 | value = new GH_HeGraph3d(); 53 | return GH_GetterResult.success; 54 | } 55 | 56 | 57 | /// 58 | protected override GH_GetterResult Prompt_Plural(ref List values) 59 | { 60 | values = new List(); 61 | return GH_GetterResult.success; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SlurGH/Params/SpatialSlur/HeMesh3dParam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using Grasshopper.Kernel; 5 | 6 | using SpatialSlur.Grasshopper.Types; 7 | 8 | /* 9 | * Notes 10 | */ 11 | 12 | namespace SpatialSlur.Grasshopper.Params 13 | { 14 | /// 15 | /// 16 | /// 17 | public class HeMesh3dParam : GH_PersistentParam 18 | { 19 | /// 20 | /// 21 | /// 22 | public HeMesh3dParam() 23 | :base("HeMesh", "HeMesh", "", "SpatialSlur", "Parameters") 24 | { 25 | } 26 | 27 | 28 | /// 29 | public override GH_Exposure Exposure 30 | { 31 | get { return GH_Exposure.primary; } 32 | } 33 | 34 | 35 | /// 36 | protected override Bitmap Icon 37 | { 38 | get { return null; } 39 | } 40 | 41 | 42 | /// 43 | public override Guid ComponentGuid 44 | { 45 | get { return new Guid("{AEEA983D-0B68-44F0-B908-C5B3FCB09C13}"); } 46 | } 47 | 48 | 49 | /// 50 | protected override GH_GetterResult Prompt_Singular(ref GH_HeMesh3d value) 51 | { 52 | value = new GH_HeMesh3d(); 53 | return GH_GetterResult.success; 54 | } 55 | 56 | 57 | /// 58 | protected override GH_GetterResult Prompt_Plural(ref List values) 59 | { 60 | values = new List(); 61 | return GH_GetterResult.success; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SlurGH/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SlurGH")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("David Reeves")] 11 | [assembly: AssemblyProduct("SlurGH")] 12 | [assembly: AssemblyCopyright("Copyright © David Reeves 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("bc254a97-352c-41d5-bebe-cf792abe454d")] // This will also be the Guid of the Rhino plug-in 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion(SpatialSlur.AssemblyInfo.VersionNumber)] -------------------------------------------------------------------------------- /SlurGH/SlurGHInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using Grasshopper.Kernel; 4 | 5 | namespace SpatialSlur.Grasshopper 6 | { 7 | /// 8 | /// 9 | /// 10 | public class SlurGHInfo : GH_AssemblyInfo 11 | { 12 | private const string _version = "0.3.0"; 13 | 14 | 15 | /// 16 | public override string Name 17 | { 18 | get { return "SpatialSlur.SlurGH"; } 19 | } 20 | 21 | 22 | /// 23 | public override Bitmap Icon 24 | { 25 | get { return null; } 26 | } 27 | 28 | 29 | /// 30 | public override string Description 31 | { 32 | get { return ""; } 33 | } 34 | 35 | 36 | /// 37 | public override Guid Id 38 | { 39 | get { return new Guid("8546948e-7b1e-4e42-beb9-a924be0b7964"); } 40 | } 41 | 42 | 43 | /// 44 | public override string AuthorName 45 | { 46 | get { return "David Reeves"; } 47 | } 48 | 49 | 50 | /// 51 | public override string AuthorContact 52 | { 53 | get { return "http://spatialslur.com/contact/"; } 54 | } 55 | 56 | 57 | /// 58 | public override string AssemblyVersion 59 | { 60 | get => _version; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SpatialSlur/Collections/Extensions/ArrayViewExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur 12 | { 13 | /// 14 | /// 15 | /// 16 | public static partial class ArrayViewExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static void Convert(this ArrayView source, Func converter, ArrayView result, bool parallel = false) 28 | { 29 | ReadOnlyArrayViewExtensions.Convert(source, converter, result, parallel); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SpatialSlur/Collections/Extensions/IDictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | /* 4 | * Notes 5 | */ 6 | 7 | namespace SpatialSlur 8 | { 9 | /// 10 | /// 11 | /// 12 | public static class IDictionaryExtensions 13 | { 14 | /// 15 | /// Assigns the contents of another dictionary to this one. 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static void Set(this IDictionary source, IDictionary other) 22 | { 23 | foreach (var pair in other) 24 | source[pair.Key] = pair.Value; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpatialSlur/Collections/Extensions/ReadOnlyArrayViewExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Threading.Tasks; 9 | 10 | using SpatialSlur.Collections; 11 | 12 | namespace SpatialSlur 13 | { 14 | /// 15 | /// 16 | /// 17 | public static partial class ReadOnlyArrayViewExtensions 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static void Convert(this ReadOnlyArrayView source, Func converter, ArrayView result, bool parallel = false) 29 | { 30 | if (parallel) 31 | { 32 | Parallel.ForEach(Partitioner.Create(0, source.Count), range => 33 | { 34 | for (int i = range.Item1; i < range.Item2; i++) 35 | result[i] = converter(source[i]); 36 | }); 37 | } 38 | else 39 | { 40 | for (int i = 0; i < source.Count; i++) 41 | result[i] = converter(source[i]); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SpatialSlur/Collections/ReadOnlySet.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections; 8 | using System.Collections.Generic; 9 | 10 | namespace SpatialSlur.Collections 11 | { 12 | /// 13 | /// 14 | /// 15 | /// 16 | public struct ReadOnlySet : IEnumerable 17 | { 18 | #region Static Members 19 | 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static implicit operator ReadOnlySet(HashSet source) 25 | { 26 | return new ReadOnlySet(source); 27 | } 28 | 29 | #endregion 30 | 31 | 32 | private HashSet _source; 33 | 34 | 35 | /// 36 | /// 37 | /// 38 | /// 39 | public ReadOnlySet(HashSet source) 40 | { 41 | _source = source; 42 | } 43 | 44 | 45 | /// 46 | /// 47 | /// 48 | public int Count 49 | { 50 | get { return _source.Count; } 51 | } 52 | 53 | 54 | /// 55 | /// 56 | /// 57 | public bool HasSource 58 | { 59 | get => _source != null; 60 | } 61 | 62 | 63 | /// 64 | /// 65 | /// 66 | /// 67 | /// 68 | public bool Contains(T item) 69 | { 70 | return _source.Contains(item); 71 | } 72 | 73 | 74 | /// 75 | /// 76 | /// 77 | /// 78 | public HashSet.Enumerator GetEnumerator() 79 | { 80 | return _source.GetEnumerator(); 81 | } 82 | 83 | 84 | #region Explicit Interface Implementations 85 | 86 | IEnumerator IEnumerable.GetEnumerator() 87 | { 88 | return GetEnumerator(); 89 | } 90 | 91 | 92 | IEnumerator IEnumerable.GetEnumerator() 93 | { 94 | return GetEnumerator(); 95 | } 96 | 97 | #endregion 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /SpatialSlur/Collections/Sequences.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | 9 | namespace SpatialSlur.Collections 10 | { 11 | /// 12 | /// 13 | /// 14 | public static class Sequences 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static IEnumerable CountFrom(int start) 22 | { 23 | while (true) 24 | yield return start++; 25 | } 26 | 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static IEnumerable CountFrom(int start, int stride) 35 | { 36 | while (true) 37 | { 38 | yield return start; 39 | start += stride; 40 | } 41 | } 42 | 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | public static IEnumerable Fibonacci() 49 | { 50 | int n0 = 0; 51 | int n1 = 1; 52 | 53 | yield return n0; 54 | yield return n1; 55 | 56 | while (true) 57 | { 58 | int n2 = n0 + n1; 59 | yield return n2; 60 | n0 = n1; 61 | n1 = n2; 62 | } 63 | } 64 | 65 | 66 | /// 67 | /// 68 | /// 69 | /// 70 | /// 71 | /// 72 | public static IEnumerable> CountInBase(int digits, int radix) 73 | { 74 | var curr = new int[digits]; 75 | var n = Pow(radix, digits); 76 | 77 | yield return curr; 78 | 79 | while (--n > 0L) 80 | { 81 | int i = 0; 82 | 83 | // increment 84 | curr[i]++; 85 | 86 | // carry 87 | while (curr[i] == radix) 88 | { 89 | curr[i++] = 0; 90 | curr[i]++; 91 | } 92 | 93 | yield return curr; 94 | } 95 | 96 | long Pow(long x, long y) 97 | { 98 | long result = 1; 99 | 100 | for (long i = 0; i < y; i++) 101 | result *= x; 102 | 103 | return result; 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SpatialSlur/Core/Atomic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace SpatialSlur 6 | { 7 | /// 8 | /// Extends atomic operations from Interlocked class to SpatialSlur primitive types 9 | /// 10 | public static class Atomic 11 | { 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public static void Exchange(ref Vector2i v0, Vector2i v1) 18 | { 19 | Interlocked.Exchange(ref v0.X, v1.X); 20 | Interlocked.Exchange(ref v0.Y, v1.Y); 21 | } 22 | 23 | 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | public static void Exchange(ref Vector2d v0, Vector2d v1) 30 | { 31 | Interlocked.Exchange(ref v0.X, v1.X); 32 | Interlocked.Exchange(ref v0.Y, v1.Y); 33 | } 34 | 35 | 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | public static void Exchange(ref Vector3i v0, Vector3i v1) 42 | { 43 | Interlocked.Exchange(ref v0.X, v1.X); 44 | Interlocked.Exchange(ref v0.Y, v1.Y); 45 | Interlocked.Exchange(ref v0.Z, v1.Z); 46 | } 47 | 48 | 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | public static void Exchange(ref Vector3f v0, Vector3f v1) 55 | { 56 | Interlocked.Exchange(ref v0.X, v1.X); 57 | Interlocked.Exchange(ref v0.Y, v1.Y); 58 | Interlocked.Exchange(ref v0.Z, v1.Z); 59 | } 60 | 61 | 62 | /// 63 | /// 64 | /// 65 | /// 66 | /// 67 | public static void Exchange(ref Vector3d v0, Vector3d v1) 68 | { 69 | Interlocked.Exchange(ref v0.X, v1.X); 70 | Interlocked.Exchange(ref v0.Y, v1.Y); 71 | Interlocked.Exchange(ref v0.Z, v1.Z); 72 | } 73 | 74 | 75 | /// 76 | /// 77 | /// 78 | /// 79 | /// 80 | public static void Exchange(ref Vector4d v0, Vector4d v1) 81 | { 82 | Interlocked.Exchange(ref v0.X, v1.X); 83 | Interlocked.Exchange(ref v0.Y, v1.Y); 84 | Interlocked.Exchange(ref v0.Z, v1.Z); 85 | Interlocked.Exchange(ref v0.W, v1.W); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SpatialSlur/Core/Extensions/ColorExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Drawing; 7 | 8 | 9 | namespace SpatialSlur 10 | { 11 | /// 12 | /// 13 | /// 14 | public static class ColorExtensions 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static Color LerpTo(this Color c, Color other, double t) 24 | { 25 | int a = (int)(c.A + (other.A - c.A) * t); 26 | int r = (int)(c.R + (other.R - c.R) * t); 27 | int g = (int)(c.G + (other.G - c.G) * t); 28 | int b = (int)(c.B + (other.B - c.B) * t); 29 | return Color.FromArgb(a, r, g, b); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SpatialSlur/Core/Extensions/GenericExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace SpatialSlur 9 | { 10 | /// 11 | /// 12 | /// 13 | public static class GenericExtensions 14 | { 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static IEnumerable Yield(this T item) 22 | { 23 | yield return item; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpatialSlur/Core/Matrix.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace SpatialSlur 13 | { 14 | /// 15 | /// 16 | /// 17 | public static partial class Matrix 18 | { 19 | /// 20 | /// Returns the entries of the covariance matrix in row-major order. 21 | /// 22 | /// 23 | /// 24 | public static void GetCovariance(IEnumerable vectors, double[] result) 25 | { 26 | var mean = new double[vectors.First().Length]; 27 | vectors.Mean(mean); 28 | GetCovariance(vectors, mean, result); 29 | } 30 | 31 | 32 | /// 33 | /// Returns the entries of the covariance matrix in row-major order. 34 | /// 35 | /// 36 | /// 37 | /// 38 | public static void GetCovariance(IEnumerable vectors, double[] mean, double[] result) 39 | { 40 | int dim = mean.Length; 41 | int n = 0; 42 | 43 | Array.Clear(result, 0, dim * dim); 44 | 45 | // calculate uppper triangular values 46 | foreach (double[] v in vectors) 47 | { 48 | for (int i = 0; i < dim; i++) 49 | { 50 | double di = v[i] - mean[i]; 51 | 52 | for (int j = i; j < dim; j++) 53 | result[i * dim + j] += di * (v[j] - mean[j]); 54 | } 55 | 56 | n++; 57 | } 58 | 59 | var t = 1.0 / n; 60 | 61 | // average and set lower triangular values 62 | for (int i = 0; i < dim; i++) 63 | { 64 | result[i * dim + i] *= t; // diagonal entry 65 | 66 | // lower triangular 67 | for (int j = i + 1; j < dim; j++) 68 | result[j * dim + i] = result[i * dim + j] *= t; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SpatialSlur/Core/Utilities.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace SpatialSlur 10 | { 11 | /// 12 | /// Static class for stray methods that don't yet fit anywhere else (boo). 13 | /// 14 | public static class Utilities 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | public static void Swap(ref U a, ref U b) 23 | { 24 | var c = a; 25 | a = b; 26 | b = c; 27 | } 28 | 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | public static void BoundsCheck(int index, int count) 36 | { 37 | if ((uint)index >= (uint)count) 38 | throw new IndexOutOfRangeException(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Body.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Dynamics 9 | { 10 | /// 11 | /// 12 | /// 13 | [Serializable] 14 | public readonly struct Body 15 | { 16 | /// 17 | public readonly BodyPosition Position; 18 | 19 | /// 20 | public readonly BodyRotation Rotation; 21 | 22 | 23 | /// 24 | /// 25 | /// 26 | /// 27 | public Body(Vector3d position) 28 | { 29 | Position = new BodyPosition(position); 30 | Rotation = null; 31 | } 32 | 33 | 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public Body(Vector3d position, Quaterniond rotation) 40 | { 41 | Position = new BodyPosition(position); 42 | Rotation = new BodyRotation(rotation); 43 | } 44 | 45 | 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | public Body(BodyPosition position, BodyRotation rotation) 52 | { 53 | Position = position; 54 | Rotation = rotation; 55 | } 56 | 57 | 58 | /// 59 | /// 60 | /// 61 | /// 62 | private Body(Body other) 63 | { 64 | Position = other.Position?.Duplicate(); 65 | Rotation = other.Rotation?.Duplicate(); 66 | } 67 | 68 | 69 | /// 70 | /// Returns a deep copy of this body. 71 | /// 72 | /// 73 | public Body Duplicate() 74 | { 75 | return new Body(this); 76 | } 77 | 78 | 79 | /// 80 | /// 81 | /// 82 | /// 83 | /// 84 | public void Deconstruct(out BodyPosition position, out BodyRotation rotation) 85 | { 86 | position = Position; 87 | rotation = Rotation; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/ConstraintSolverSettings.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Dynamics 9 | { 10 | /// 11 | /// 12 | /// 13 | [Serializable] 14 | public class ConstraintSolverSettings 15 | { 16 | private double _linearDamping = 0.1; 17 | private double _angularDamping = 0.1; 18 | 19 | private double _linearTolerance = 1.0e-4; 20 | private double _angularTolerance = 1.0e-4; 21 | 22 | private double _timeStep = 1.0; 23 | 24 | 25 | /// 26 | /// 27 | /// 28 | public double LinearDamping 29 | { 30 | get { return _linearDamping; } 31 | set 32 | { 33 | if (value < 0.0 || value > 1.0) 34 | throw new ArgumentOutOfRangeException("The value must be between 0.0 and 1.0."); 35 | 36 | _linearDamping = value; 37 | } 38 | } 39 | 40 | 41 | /// 42 | /// 43 | /// 44 | public double AngularDamping 45 | { 46 | get { return _angularDamping; } 47 | set 48 | { 49 | if (value < 0.0 || value > 1.0) 50 | throw new ArgumentOutOfRangeException("The value must be between 0.0 and 1.0."); 51 | 52 | _angularDamping = value; 53 | } 54 | } 55 | 56 | 57 | /// 58 | /// 59 | /// 60 | public double LinearTolerance 61 | { 62 | get { return _linearTolerance; } 63 | set 64 | { 65 | if (value < 0.0) 66 | throw new ArgumentOutOfRangeException("The value cannot be negative."); 67 | 68 | _linearTolerance = value; 69 | } 70 | } 71 | 72 | 73 | /// 74 | /// 75 | /// 76 | public double AngularTolerance 77 | { 78 | get { return _angularTolerance; } 79 | set 80 | { 81 | if (value < 0.0) 82 | throw new ArgumentOutOfRangeException("The value cannot be negative."); 83 | 84 | _angularTolerance = value; 85 | } 86 | } 87 | 88 | 89 | /// 90 | /// 91 | /// 92 | public double TimeStep 93 | { 94 | get { return _timeStep; } 95 | set 96 | { 97 | if (value < 0.0) 98 | throw new ArgumentOutOfRangeException("The value cannot be negative."); 99 | 100 | _timeStep = value; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Cocircular.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class Cocircular : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public Cocircular(double weight = 1.0) 24 | : base(weight) 25 | { 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Cocircular(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 42 | { 43 | int n = indices.Count; 44 | 45 | if (n < 4 || !Geometry.FitCircleToPoints(Indices.Select(i => bodies[i].Position.Current), out Vector3d p, out Vector3d z, out double r)) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | for (int i = 0; i < n; i++) 52 | { 53 | var d = Vector3d.Project(p - bodies[indices[i]].Position.Current, z); 54 | deltas[i] = d * (1.0 - r / d.Length); 55 | } 56 | 57 | return true; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Coincident.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class Coincident : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public Coincident(double weight = 1.0) 24 | : base(weight) 25 | { 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Coincident(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 42 | { 43 | int n = indices.Count; 44 | 45 | if(n < 2) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | var p = Indices.Select(i => bodies[i].Position.Current).Mean(); 52 | 53 | for (int i = 0; i < n; i++) 54 | deltas[i] = p - bodies[indices[i]].Position.Current; 55 | 56 | return true; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Colinear.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class Colinear : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public Colinear(double weight = 1.0) 24 | : base(weight) 25 | { 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Colinear(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 42 | { 43 | int n = indices.Count; 44 | 45 | if(n < 3 || !Geometry.FitLineToPoints(Indices.Select(i => bodies[i].Position.Current), out Vector3d p, out Vector3d d)) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | for (int i = 0; i < n; i++) 52 | deltas[i] = Vector3d.Reject(p - bodies[indices[i]].Position.Current, d); 53 | 54 | return true; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Constraint.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Dynamics.Constraints 9 | { 10 | /// 11 | /// Contains any implementation details common to ALL constraints. 12 | /// 13 | [Serializable] 14 | public abstract class Constraint 15 | { 16 | private double _weight; 17 | 18 | 19 | /// 20 | /// 21 | /// 22 | /// 23 | public double Weight 24 | { 25 | get { return _weight; } 26 | set 27 | { 28 | if (value < 0.0) 29 | throw new ArgumentOutOfRangeException("The value cannot be negative."); 30 | 31 | _weight = value; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Coplanar.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class Coplanar : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public Coplanar(double weight = 1.0) 24 | : base(weight) 25 | { 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Coplanar(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 42 | { 43 | int n = indices.Count; 44 | 45 | if(n < 4 || !Geometry.FitPlaneToPoints(Indices.Select(i => bodies[i].Position.Current), out Vector3d p, out Vector3d z)) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | for (int i = 0; i < n; i++) 52 | deltas[i] = Vector3d.Project(p - bodies[indices[i]].Position.Current, z); 53 | 54 | return true; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/Cospherical.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class Cospherical : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public Cospherical(double weight = 1.0) 24 | : base(weight) 25 | { 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Cospherical(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 42 | { 43 | int n = indices.Count; 44 | 45 | if(n < 4 || !Geometry.FitSphereToPoints(Indices.Select(i => bodies[i].Position.Current), out Vector3d p, out double r)) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | for (int i = 0; i < n; i++) 52 | { 53 | var d = p - bodies[indices[i]].Position.Current; 54 | deltas[i] = d * (1.0 - r / d.Length); 55 | } 56 | 57 | return true; 58 | } 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/EqualizeLengths.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// Each successive pair of handles represents a line segment. 15 | /// 16 | [Serializable] 17 | public class EqualizeLengths : PositionGroup 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public EqualizeLengths(double weight = 1.0) 24 | { 25 | Weight = weight; 26 | } 27 | 28 | 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public EqualizeLengths(IEnumerable indices, double weight = 1.0) 35 | : base(indices, weight) 36 | { 37 | } 38 | 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 48 | { 49 | int n = indices.Count; 50 | 51 | // check if sufficient number of bodies 52 | if (n < 4) 53 | { 54 | deltas.Clear(); 55 | return false; 56 | } 57 | 58 | var target = 0.0; 59 | 60 | // calculate target as mean length 61 | for (int i = 0; i < n; i += 2) 62 | { 63 | var d = bodies[indices[i + 1]].Position.Current - bodies[indices[i]].Position.Current; 64 | var m = d.Length; 65 | target += m; 66 | 67 | // cache to avoid redundant calcs 68 | deltas[i] = d; 69 | deltas[i + 1].X = m; 70 | } 71 | 72 | target /= n >> 1; 73 | 74 | // calculate deltas 75 | for (int i = 0; i < n; i += 2) 76 | { 77 | var d = deltas[i]; 78 | var m = deltas[i + 1].X; 79 | 80 | d *= (1.0 - target / m) * 0.5; 81 | deltas[i] = d; 82 | deltas[i + 1] = -d; 83 | } 84 | 85 | return true; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/InsideBounds.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class InsideBounds : Constraint, IConstraint 18 | { 19 | private Vector3d _delta; 20 | private int _index; 21 | 22 | private Interval3d _bounds; 23 | private bool _apply; 24 | 25 | 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public InsideBounds(int index, Interval3d bounds, double weight = 1.0) 33 | { 34 | _index = index; 35 | _bounds = bounds; 36 | Weight = weight; 37 | } 38 | 39 | 40 | /// 41 | /// 42 | /// 43 | public int Index 44 | { 45 | get { return _index; } 46 | set { _index = value; } 47 | } 48 | 49 | 50 | /// 51 | /// 52 | /// 53 | public Interval3d Bounds 54 | { 55 | get { return _bounds; } 56 | set { _bounds = value; } 57 | } 58 | 59 | 60 | /// 61 | public void Calculate(ReadOnlyArrayView bodies) 62 | { 63 | var p = bodies[_index].Position.Current; 64 | 65 | if (_bounds.Contains(p)) 66 | { 67 | _delta = Vector3d.Zero; 68 | _apply = false; 69 | return; 70 | } 71 | 72 | _delta = _bounds.Clamp(p) - p; 73 | _apply = true; 74 | } 75 | 76 | 77 | /// 78 | public void Apply(ReadOnlyArrayView bodies) 79 | { 80 | if (_apply) 81 | bodies[_index].Position.AddDelta(_delta, Weight); 82 | } 83 | 84 | 85 | /// 86 | public void GetEnergy(out double linear, out double angular) 87 | { 88 | linear = _delta.Length; 89 | angular = 0.0; 90 | } 91 | 92 | 93 | #region Explicit Interface Implementations 94 | 95 | bool IConstraint.AffectsPosition 96 | { 97 | get { return true; } 98 | } 99 | 100 | 101 | bool IConstraint.AffectsRotation 102 | { 103 | get { return false; } 104 | } 105 | 106 | 107 | IEnumerable IConstraint.Indices 108 | { 109 | get { yield return _index; } 110 | set { _index = value.First(); } 111 | } 112 | 113 | #endregion 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/LaplacianSmooth.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using SpatialSlur.Collections; 9 | 10 | namespace SpatialSlur.Dynamics.Constraints 11 | { 12 | /// 13 | /// 14 | /// 15 | [Serializable] 16 | public class LaplacianSmooth : PositionGroup 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | public LaplacianSmooth(double weight = 1.0) 23 | : base(weight) 24 | { 25 | } 26 | 27 | 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | public LaplacianSmooth(IEnumerable indices, double weight = 1.0) 34 | : base(indices, weight) 35 | { 36 | } 37 | 38 | 39 | /// 40 | protected override bool Calculate(ReadOnlyArrayView bodies, ReadOnlyArrayView indices, ArrayView deltas) 41 | { 42 | int n = indices.Count; 43 | 44 | // check if sufficient number of bodies 45 | if (n < 3) 46 | { 47 | deltas.Clear(); 48 | return false; 49 | } 50 | 51 | var sum = new Vector3d(); 52 | 53 | for (int i = 1; i < n; i++) 54 | sum += bodies[indices[i]].Position.Current; 55 | 56 | var t = 1.0 / (n - 1); 57 | var d = (sum * t - bodies[indices[0]].Position.Current) * 0.5; 58 | 59 | // apply projection to center 60 | deltas[0] = d; 61 | d *= -t; 62 | 63 | // distribute reverse among 1 ring 64 | for (int i = 1; i < n; i++) 65 | deltas[i] = d; 66 | 67 | return true; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/MinimizeDistance.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using SpatialSlur.Collections; 9 | 10 | namespace SpatialSlur.Dynamics.Constraints 11 | { 12 | /// 13 | /// 14 | /// 15 | [Serializable] 16 | public class MinimizeDistance : Constraint, IConstraint 17 | { 18 | private Vector3d _delta; 19 | private int _i0, _i1; 20 | 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public MinimizeDistance(int index0, int index1, double weight = 1.0) 29 | { 30 | _i0 = index0; 31 | _i1 = index1; 32 | Weight = weight; 33 | } 34 | 35 | 36 | /// 37 | /// 38 | /// 39 | public int Index0 40 | { 41 | get { return _i0; } 42 | set { _i0 = value; } 43 | } 44 | 45 | 46 | /// 47 | /// 48 | /// 49 | public int Index1 50 | { 51 | get { return _i1; } 52 | set { _i1 = value; } 53 | } 54 | 55 | 56 | /// 57 | public void Calculate(ReadOnlyArrayView bodies) 58 | { 59 | _delta = (bodies[_i1].Position.Current - bodies[_i0].Position.Current) * 0.5; 60 | } 61 | 62 | 63 | /// 64 | public void Apply(ReadOnlyArrayView bodies) 65 | { 66 | bodies[_i0].Position.AddDelta(_delta, Weight); 67 | bodies[_i1].Position.AddDelta(-_delta, Weight); 68 | } 69 | 70 | 71 | /// 72 | public void GetEnergy(out double linear, out double angular) 73 | { 74 | linear = _delta.Length * 2.0; 75 | angular = 0.0; 76 | } 77 | 78 | 79 | #region Explicit Interface Implementations 80 | 81 | bool IConstraint.AffectsPosition 82 | { 83 | get { return true; } 84 | } 85 | 86 | 87 | bool IConstraint.AffectsRotation 88 | { 89 | get { return false; } 90 | } 91 | 92 | 93 | IEnumerable IConstraint.Indices 94 | { 95 | get 96 | { 97 | yield return _i0; 98 | yield return _i1; 99 | } 100 | set 101 | { 102 | var itr = value.GetEnumerator(); 103 | 104 | itr.MoveNext(); 105 | _i0 = itr.Current; 106 | 107 | itr.MoveNext(); 108 | _i1 = itr.Current; 109 | } 110 | } 111 | 112 | #endregion 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnCurve.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnCurve : OnTarget 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public OnCurve(int index, Curve curve, double weight = 1.0) 26 | : base(index, curve, weight) 27 | { 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | protected override Vector3d GetClosestPoint(Vector3d point) 37 | { 38 | var crv = Target; 39 | crv.ClosestPoint(point, out double t); 40 | return crv.PointAt(t); 41 | } 42 | } 43 | } 44 | 45 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnExtendedMesh.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnExtendedMesh : OnTarget 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public OnExtendedMesh(int index, Mesh mesh, double weight = 1.0) 26 | : base(index, mesh, weight) 27 | { 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | protected override Vector3d GetClosestPoint(Vector3d point) 37 | { 38 | var mesh = Target; 39 | var mp = mesh.ClosestMeshPoint(point, 0.0); 40 | 41 | Vector3d cp = mesh.PointAt(mp); 42 | Vector3d cn = mesh.NormalAt(mp); 43 | return point + Vector3d.Project(cp - point, cn); 44 | } 45 | } 46 | } 47 | 48 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnExtendedSurface.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnExtendedSurface : OnTarget 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public OnExtendedSurface(int index, Surface surface, double weight = 1.0) 26 | : base(index, surface, weight) 27 | { 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | protected override Vector3d GetClosestPoint(Vector3d point) 37 | { 38 | var srf = Target; 39 | srf.ClosestPoint(point, out double u, out double v); 40 | 41 | Vector3d cp = srf.PointAt(u, v); 42 | Vector3d cn = srf.NormalAt(u, v); 43 | return point + Vector3d.Project(cp - point, cn); 44 | } 45 | } 46 | } 47 | 48 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnMesh.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnMesh : OnTarget 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public OnMesh(int index, Mesh mesh, double weight = 1.0) 26 | :base(index, mesh, weight) 27 | { 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | protected override Vector3d GetClosestPoint(Vector3d point) 37 | { 38 | return Target.ClosestPoint(point); 39 | } 40 | } 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnPlane.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnPlane : Constraint, IConstraint 18 | { 19 | private Vector3d _delta; 20 | private int _index; 21 | 22 | private Vector3d _origin; 23 | private Vector3d _normal; 24 | 25 | 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | public OnPlane(int index, Vector3d origin, Vector3d normal, double weight = 1.0) 34 | { 35 | _index = index; 36 | _origin = origin; 37 | _normal = normal; 38 | Weight = weight; 39 | } 40 | 41 | 42 | /// 43 | /// 44 | /// 45 | public int Index 46 | { 47 | get { return _index; } 48 | set { _index = value; } 49 | } 50 | 51 | 52 | /// 53 | /// 54 | /// 55 | public Vector3d Origin 56 | { 57 | get { return _origin; } 58 | set { _origin = value; } 59 | } 60 | 61 | 62 | /// 63 | /// 64 | /// 65 | public Vector3d Normal 66 | { 67 | get { return _normal; } 68 | set { _normal = value; } 69 | } 70 | 71 | 72 | /// 73 | public void Calculate(ReadOnlyArrayView bodies) 74 | { 75 | _delta = Vector3d.Project(_origin - bodies[_index].Position.Current, _normal); 76 | } 77 | 78 | 79 | /// 80 | public void Apply(ReadOnlyArrayView bodies) 81 | { 82 | bodies[_index].Position.AddDelta(_delta, Weight); 83 | } 84 | 85 | 86 | /// 87 | public void GetEnergy(out double linear, out double angular) 88 | { 89 | linear = _delta.Length; 90 | angular = 0.0; 91 | } 92 | 93 | 94 | #region Explicit Interface Implementations 95 | 96 | bool IConstraint.AffectsPosition 97 | { 98 | get { return true; } 99 | } 100 | 101 | 102 | bool IConstraint.AffectsRotation 103 | { 104 | get { return false; } 105 | } 106 | 107 | 108 | IEnumerable IConstraint.Indices 109 | { 110 | get { yield return _index; } 111 | set { _index = value.First(); } 112 | } 113 | 114 | #endregion 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnPosition.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | 14 | /// 15 | /// 16 | /// 17 | [Serializable] 18 | public class OnPosition : Constraint, IConstraint 19 | { 20 | private Vector3d _delta; 21 | private int _index; 22 | 23 | private Vector3d _target; 24 | 25 | 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public OnPosition(int index, Vector3d position, double weight = 1.0) 33 | { 34 | _index = index; 35 | _target = position; 36 | Weight = weight; 37 | } 38 | 39 | 40 | /// 41 | /// 42 | /// 43 | public int Index 44 | { 45 | get { return _index; } 46 | set { _index = value; } 47 | } 48 | 49 | 50 | /// 51 | /// 52 | /// 53 | public Vector3d Target 54 | { 55 | get { return _target; } 56 | set { _target = value; } 57 | } 58 | 59 | 60 | /// 61 | public void Calculate(ReadOnlyArrayView bodies) 62 | { 63 | _delta = _target - bodies[_index].Position.Current; 64 | } 65 | 66 | 67 | /// 68 | public void Apply(ReadOnlyArrayView bodies) 69 | { 70 | bodies[_index].Position.AddDelta(_delta, Weight); 71 | } 72 | 73 | 74 | /// 75 | public void GetEnergy(out double linear, out double angular) 76 | { 77 | linear = _delta.Length; 78 | angular = 0.0; 79 | } 80 | 81 | 82 | #region Explicit Interface Implementations 83 | 84 | bool IConstraint.AffectsPosition 85 | { 86 | get { return true; } 87 | } 88 | 89 | 90 | bool IConstraint.AffectsRotation 91 | { 92 | get { return false; } 93 | } 94 | 95 | 96 | IEnumerable IConstraint.Indices 97 | { 98 | get { yield return _index; } 99 | set { _index = value.First(); } 100 | } 101 | 102 | #endregion 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnRotation.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnRotation : Constraint, IConstraint 18 | { 19 | private Vector3d _delta; 20 | private int _index; 21 | 22 | private Quaterniond _target; 23 | 24 | 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | public OnRotation(int index, Quaterniond target, double weight = 1.0) 32 | { 33 | _index = index; 34 | _target = target; 35 | Weight = weight; 36 | } 37 | 38 | 39 | /// 40 | /// 41 | /// 42 | public int Index 43 | { 44 | get { return _index; } 45 | set { _index = value; } 46 | } 47 | 48 | 49 | /// 50 | /// 51 | /// 52 | public Quaterniond Target 53 | { 54 | get { return _target; } 55 | set { _target = value; } 56 | } 57 | 58 | 59 | /// 60 | public void Calculate(ReadOnlyArrayView bodies) 61 | { 62 | _delta = Quaterniond.CreateFromTo(bodies[_index].Rotation.Current, _target).ToAxisAngle(); 63 | } 64 | 65 | 66 | /// 67 | public void Apply(ReadOnlyArrayView bodies) 68 | { 69 | bodies[_index].Rotation.AddDelta(_delta, Weight); 70 | } 71 | 72 | 73 | /// 74 | public void GetEnergy(out double linear, out double angular) 75 | { 76 | linear = 0.0; 77 | angular = _delta.Length; 78 | } 79 | 80 | 81 | #region Explicit Interface Implementations 82 | 83 | bool IConstraint.AffectsPosition 84 | { 85 | get { return false; } 86 | } 87 | 88 | 89 | bool IConstraint.AffectsRotation 90 | { 91 | get { return true; } 92 | } 93 | 94 | 95 | IEnumerable IConstraint.Indices 96 | { 97 | get { yield return _index; } 98 | set { _index = value.First(); } 99 | } 100 | 101 | #endregion 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Constraints/OnSurface.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Dynamics.Constraints 12 | { 13 | /// 14 | /// 15 | /// 16 | [Serializable] 17 | public class OnSurface : OnTarget 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public OnSurface(int index, Surface surface, double weight = 1.0) 26 | : base(index, surface, weight) 27 | { 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | protected override Vector3d GetClosestPoint(Vector3d point) 37 | { 38 | var srf = Target; 39 | 40 | srf.ClosestPoint(point, out double u, out double v); 41 | return srf.PointAt(u, v); 42 | } 43 | } 44 | } 45 | 46 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Extensions/IEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SpatialSlur.Dynamics; 8 | 9 | namespace SpatialSlur 10 | { 11 | /// 12 | /// 13 | /// 14 | public static partial class IEnumerableExtensions 15 | { 16 | #region IEnumerable 17 | 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static bool AreSatisfied(this IEnumerable constraints, double linearTolerance, double angularTolerance) 27 | where T : IConstraint 28 | { 29 | foreach(var c in constraints) 30 | { 31 | c.GetEnergy(out double lin, out double ang); 32 | if (lin >= linearTolerance || ang >= angularTolerance) return false; 33 | } 34 | 35 | return true; 36 | } 37 | 38 | 39 | /// 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | public static void GetEnergySum(this IEnumerable constraints, out double linear, out double angular) 46 | where T : IConstraint 47 | { 48 | linear = 0.0; 49 | angular = 0.0; 50 | 51 | foreach (var c in constraints) 52 | { 53 | c.GetEnergy(out double lin, out double ang); 54 | linear += lin; 55 | angular += ang; 56 | } 57 | } 58 | 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Forces/Force.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Dynamics.Forces 9 | { 10 | /// 11 | /// 12 | /// 13 | public abstract class Force 14 | { 15 | private double _strength; 16 | 17 | 18 | /// 19 | /// 20 | /// 21 | /// 22 | public double Strength 23 | { 24 | get { return _strength; } 25 | set { _strength = value; } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Forces/ForceField.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | using SpatialSlur.Fields; 11 | 12 | namespace SpatialSlur.Dynamics.Forces 13 | { 14 | /// 15 | /// 16 | /// 17 | [Serializable] 18 | public class ForceField : Force, IConstraint 19 | { 20 | private IField3d _field; 21 | private Vector3d _delta; 22 | private int _index; 23 | 24 | 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | public ForceField(int index, IField3d field, double strength = 1.0) 32 | { 33 | _index = index; 34 | Field = field; 35 | Strength = strength; 36 | } 37 | 38 | 39 | /// 40 | /// 41 | /// 42 | public int Index 43 | { 44 | get { return _index; } 45 | set { _index = value; } 46 | } 47 | 48 | 49 | /// 50 | /// 51 | /// 52 | public IField3d Field 53 | { 54 | get { return _field; } 55 | set { _field = value ?? throw new ArgumentNullException(); } 56 | } 57 | 58 | 59 | /// 60 | public void Calculate(ReadOnlyArrayView bodies) 61 | { 62 | _delta = _field.ValueAt(bodies[_index].Position.Current) * Strength; 63 | } 64 | 65 | 66 | /// 67 | public void Apply(ReadOnlyArrayView bodies) 68 | { 69 | bodies[_index].Position.AddForce(_delta); 70 | } 71 | 72 | 73 | /// 74 | public void GetEnergy(out double linear, out double angular) 75 | { 76 | linear = _delta.Length; 77 | angular = 0.0; 78 | } 79 | 80 | 81 | #region Explicit Interface Implementations 82 | 83 | bool IConstraint.AffectsPosition 84 | { 85 | get { return true; } 86 | } 87 | 88 | 89 | bool IConstraint.AffectsRotation 90 | { 91 | get { return false; } 92 | } 93 | 94 | 95 | IEnumerable IConstraint.Indices 96 | { 97 | get { yield return _index; } 98 | set { _index = value.First(); } 99 | } 100 | 101 | #endregion 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Forces/Weight.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using SpatialSlur.Collections; 10 | 11 | namespace SpatialSlur.Dynamics.Forces 12 | { 13 | /// 14 | /// Applies a force proportional to the mass of each particle. 15 | /// 16 | [Serializable] 17 | public class Weight : Force, IConstraint 18 | { 19 | private Vector3d _acceleration; 20 | private Vector3d _delta; 21 | private int _index; 22 | 23 | 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | public Weight(int index, Vector3d acceleration, double strength = 1.0) 31 | { 32 | _index = index; 33 | _acceleration = acceleration; 34 | Strength = strength; 35 | } 36 | 37 | 38 | /// 39 | /// 40 | /// 41 | public int Index 42 | { 43 | get { return _index; } 44 | set { _index = value; } 45 | } 46 | 47 | 48 | /// 49 | /// 50 | /// 51 | public Vector3d Acceleration 52 | { 53 | get { return _acceleration; } 54 | set { _acceleration = value; } 55 | } 56 | 57 | 58 | /// 59 | public void Calculate(ReadOnlyArrayView bodies) 60 | { 61 | _delta = _acceleration * (bodies[_index].Position.Mass * Strength); 62 | } 63 | 64 | 65 | /// 66 | public void Apply(ReadOnlyArrayView bodies) 67 | { 68 | bodies[_index].Position.AddForce(_delta); 69 | } 70 | 71 | 72 | /// 73 | public void GetEnergy(out double linear, out double angular) 74 | { 75 | linear = _delta.Length; 76 | angular = 0.0; 77 | } 78 | 79 | 80 | #region Explicit Interface Implementations 81 | 82 | bool IConstraint.AffectsPosition 83 | { 84 | get { return true; } 85 | } 86 | 87 | 88 | bool IConstraint.AffectsRotation 89 | { 90 | get { return false; } 91 | } 92 | 93 | 94 | IEnumerable IConstraint.Indices 95 | { 96 | get { yield return _index; } 97 | set { _index = value.First(); } 98 | } 99 | 100 | #endregion 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /SpatialSlur/Dynamics/Interfaces/IConstraint.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | using SpatialSlur.Collections; 8 | 9 | namespace SpatialSlur.Dynamics 10 | { 11 | /// 12 | /// 13 | /// 14 | public interface IConstraint 15 | { 16 | /// 17 | /// Gets or sets the indices of the bodies affected by this constraint. 18 | /// 19 | IEnumerable Indices { get; set; } 20 | 21 | 22 | /// 23 | /// Returns true if this constraint affects a body's position. 24 | /// 25 | bool AffectsPosition { get; } 26 | 27 | 28 | /// 29 | /// Returns true if this constraint affects a body's rotation. 30 | /// 31 | bool AffectsRotation { get; } 32 | 33 | 34 | /// 35 | /// Calculates all forces and projections associated with this constraint. 36 | /// 37 | /// 38 | void Calculate(ReadOnlyArrayView bodies); 39 | 40 | 41 | /// 42 | /// Applies calculated forces and projections to the affected bodies. 43 | /// 44 | /// 45 | void Apply(ReadOnlyArrayView bodies); 46 | 47 | 48 | /// 49 | /// Returns the energy that this constraint is trying to minimize. 50 | /// The constraint is satisfied when this equals zero. 51 | /// 52 | void GetEnergy(out double linear, out double angular); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Derived/IDWField3dDouble.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | using SpatialSlur; 9 | using SpatialSlur.Fields; 10 | 11 | using D = SpatialSlur.SlurMath.Constantsd; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | [Serializable] 19 | internal class IDWField3dDouble : IDWField3d 20 | { 21 | #region Nested Types 22 | 23 | /// 24 | /// 25 | /// 26 | internal class Factory : IDWFieldFactory 27 | { 28 | /// 29 | public override IDWField3d Create(double power, double epsilon = D.ZeroTolerance) 30 | { 31 | return new IDWField3dDouble(power, epsilon); 32 | } 33 | } 34 | 35 | #endregion 36 | 37 | 38 | /// 39 | /// 40 | /// 41 | public IDWField3dDouble(double power, double epsilon = D.ZeroTolerance) 42 | : base(power, epsilon) 43 | { 44 | } 45 | 46 | 47 | /// 48 | public sealed override IDWField3d Duplicate() 49 | { 50 | return IDWField3d.Double.CreateCopy(this); 51 | } 52 | 53 | 54 | /// 55 | public sealed override double ValueAt(Vector3d point) 56 | { 57 | double sum = 0.0; 58 | double wsum = 0.0; 59 | 60 | foreach (var obj in Objects) 61 | { 62 | double w = obj.Influence / Math.Pow(obj.DistanceTo(point) + Epsilon, Power); 63 | sum += obj.Value * w; 64 | wsum += w; 65 | } 66 | 67 | return (wsum > 0.0) ? sum / wsum : 0.0; 68 | } 69 | 70 | 71 | /// 72 | public sealed override void GradientAt(Vector3d point, out double gx, out double gy, out double gz) 73 | { 74 | throw new NotImplementedException(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Derived/IDWField3dVector3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | using SpatialSlur; 9 | using SpatialSlur.Fields; 10 | 11 | using D = SpatialSlur.SlurMath.Constantsd; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | [Serializable] 19 | internal class IDWField3dVector3d : IDWField3d 20 | { 21 | #region Nested Types 22 | 23 | /// 24 | /// 25 | /// 26 | internal class Factory : IDWFieldFactory 27 | { 28 | /// 29 | public override IDWField3d Create(double power, double epsilon = D.ZeroTolerance) 30 | { 31 | return new IDWField3dVector3d(power, epsilon); 32 | } 33 | } 34 | 35 | #endregion 36 | 37 | 38 | /// 39 | /// 40 | /// 41 | public IDWField3dVector3d(double power, double epsilon = D.ZeroTolerance) 42 | : base(power, epsilon) 43 | { 44 | } 45 | 46 | 47 | /// 48 | public sealed override IDWField3d Duplicate() 49 | { 50 | return IDWField3d.Vector3d.CreateCopy(this); 51 | } 52 | 53 | 54 | /// 55 | public sealed override Vector3d ValueAt(Vector3d point) 56 | { 57 | Vector3d sum = Vector3d.Zero; 58 | double wsum = 0.0; 59 | 60 | foreach (var obj in Objects) 61 | { 62 | double w = obj.Influence / Math.Pow(obj.DistanceTo(point) + Epsilon, Power); 63 | sum += obj.Value * w; 64 | wsum += w; 65 | } 66 | 67 | return (wsum > 0.0) ? sum / wsum : new Vector3d(); 68 | } 69 | 70 | 71 | /// 72 | public sealed override void GradientAt(Vector3d point, out Vector3d gx, out Vector3d gy, out Vector3d gz) 73 | { 74 | throw new NotImplementedException(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Derived/MeshField3dDouble.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using SpatialSlur; 10 | using SpatialSlur.Meshes; 11 | using SpatialSlur.Fields; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | [Serializable] 19 | internal class MeshField3dDouble : MeshField3d 20 | { 21 | #region Nested Types 22 | 23 | /// 24 | /// 25 | /// 26 | internal class Factory : MeshField3dFactory 27 | { 28 | /// 29 | public override MeshField3d Create(HeMesh3d mesh) 30 | { 31 | return new MeshField3dDouble(mesh); 32 | } 33 | 34 | 35 | /// 36 | public override MeshField3d Create(MeshField3d field) 37 | { 38 | return new MeshField3dDouble(field); 39 | } 40 | } 41 | 42 | #endregion 43 | 44 | 45 | /// 46 | /// 47 | /// 48 | /// 49 | public MeshField3dDouble(HeMesh3d mesh) 50 | : base(mesh) 51 | { 52 | } 53 | 54 | 55 | /// 56 | /// 57 | /// 58 | /// 59 | public MeshField3dDouble(MeshField3d other) 60 | : base(other) 61 | { 62 | } 63 | 64 | 65 | /// 66 | public sealed override MeshField3d Duplicate(bool setValues) 67 | { 68 | var result = MeshField3d.Double.Create(this); 69 | if(setValues) result.Set(this); 70 | return result; 71 | } 72 | 73 | 74 | /// 75 | public override double ValueAt(Vector3d weights, Vector3i indices) 76 | { 77 | return 78 | Values[indices.X] * weights.X + 79 | Values[indices.Y] * weights.Y + 80 | Values[indices.Z] * weights.Z; 81 | } 82 | } 83 | } 84 | 85 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Fields/Derived/MeshField3dVector3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using SpatialSlur; 10 | using SpatialSlur.Fields; 11 | using SpatialSlur.Meshes; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | [Serializable] 19 | internal class MeshField3dVector3d : MeshField3d 20 | { 21 | #region Nested Types 22 | 23 | /// 24 | /// 25 | /// 26 | internal class Factory : MeshField3dFactory 27 | { 28 | /// 29 | public override MeshField3d Create(HeMesh3d mesh) 30 | { 31 | return new MeshField3dVector3d(mesh); 32 | } 33 | 34 | 35 | /// 36 | public override MeshField3d Create(MeshField3d field) 37 | { 38 | return new MeshField3dVector3d(field); 39 | } 40 | } 41 | 42 | #endregion 43 | 44 | 45 | /// 46 | /// 47 | /// 48 | /// 49 | public MeshField3dVector3d(HeMesh3d mesh) 50 | : base(mesh) 51 | { 52 | } 53 | 54 | 55 | /// 56 | /// 57 | /// 58 | /// 59 | public MeshField3dVector3d(MeshField3d other) 60 | : base(other) 61 | { 62 | } 63 | 64 | 65 | /// 66 | public sealed override MeshField3d Duplicate(bool setValues) 67 | { 68 | var result = MeshField3d.Vector3d.Create(this); 69 | if (setValues) result.Set(this); 70 | return result; 71 | } 72 | 73 | 74 | /// 75 | public override Vector3d ValueAt(Vector3d weights, Vector3i indices) 76 | { 77 | return 78 | Values[indices.X] * weights.X + 79 | Values[indices.Y] * weights.Y + 80 | Values[indices.Z] * weights.Z; 81 | } 82 | } 83 | } 84 | 85 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Fields/DistanceFunctions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | * 5 | * References 6 | * http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm 7 | */ 8 | 9 | using System; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Fields 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class DistanceFunctions 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static double Sphere(Vector3d point, double radius) 26 | { 27 | return point.Length - radius; 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public static double Box(Vector3d point, Vector3d size) 38 | { 39 | var d = Vector3d.Abs(point) - size; 40 | return Math.Min(d.ComponentMax, 0.0) + Vector3d.Min(d, 0.0).Length; 41 | } 42 | 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | public static double Capsule(Vector3d point, Vector3d start, Vector3d axis, double radius) 53 | { 54 | var d = point - start; 55 | var t = SlurMath.Saturate(Vector3d.Dot(d, axis) / axis.SquareLength); 56 | return (d - axis * t).Length - radius; 57 | } 58 | 59 | 60 | /// 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// 66 | public static double Union(double d0, double d1) 67 | { 68 | return Math.Min(d0, d1); 69 | } 70 | 71 | 72 | /// 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | public static double Difference(double d0, double d1) 79 | { 80 | return Math.Max(-d0, d1); 81 | } 82 | 83 | 84 | /// 85 | /// 86 | /// 87 | /// 88 | /// 89 | /// 90 | public static double Intersection(double d0, double d1) 91 | { 92 | return Math.Max(d0, d1); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Enums/IntegrationMode.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Fields 7 | { 8 | /// 9 | /// 10 | /// 11 | public enum IntegrationMode 12 | { 13 | /// 14 | Euler, 15 | /// 16 | RK2, 17 | /// 18 | RK4 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Enums/SampleMode.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Fields 7 | { 8 | /// 9 | /// Determines how the field is sampled at a given point. 10 | /// 11 | public enum SampleMode 12 | { 13 | /// 14 | Nearest, 15 | /// 16 | Linear 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Enums/WrapMode.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Fields 7 | { 8 | /// 9 | /// Determines what happens when a field is evaluated beyond its bounds. 10 | /// 11 | public enum WrapMode 12 | { 13 | /// 14 | Clamp, 15 | /// 16 | Repeat, 17 | /// 18 | Mirror 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Extensions/GridField3dFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.IO; 8 | using System.Text; 9 | 10 | using SpatialSlur; 11 | using SpatialSlur.Fields; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | public static class GridField3dFactoryExtensions 19 | { 20 | #region Vector3d 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static GridField3d CreateFromFGA(this GridField3dFactory factory, string path) 29 | { 30 | var content = File.ReadAllText(path, Encoding.ASCII); 31 | var values = content.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 32 | 33 | int nx = int.Parse(values[0]); 34 | int ny = int.Parse(values[1]); 35 | int nz = int.Parse(values[2]); 36 | 37 | Vector3d p0 = new Vector3d( 38 | double.Parse(values[3]), 39 | double.Parse(values[4]), 40 | double.Parse(values[5])); 41 | 42 | Vector3d p1 = new Vector3d( 43 | double.Parse(values[6]), 44 | double.Parse(values[7]), 45 | double.Parse(values[8])); 46 | 47 | var result = factory.Create(nx, ny, nz, new Interval3d(p0, p1)); 48 | var vecs = result.Values; 49 | int index = 0; 50 | 51 | for (int i = 9; i < values.Length; i += 3) 52 | { 53 | vecs[index++] = new Vector3d( 54 | double.Parse(values[i]), 55 | double.Parse(values[i + 1]), 56 | double.Parse(values[i + 2])); 57 | } 58 | 59 | return result; 60 | } 61 | 62 | #endregion 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Extensions/ISampledField2dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Threading.Tasks; 9 | 10 | namespace SpatialSlur.Fields 11 | { 12 | /// 13 | /// 14 | /// 15 | public static class ISampledField2dExtensions 16 | { 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static ISampledField2d Duplicate(this ISampledField2d field) 24 | where T : struct 25 | { 26 | return field.Duplicate(true); 27 | } 28 | 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public static void Sample(this ISampledField2d field, IField2d other, bool parallel = false) 38 | { 39 | if (parallel) 40 | Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); 41 | else 42 | Body(0, field.Count); 43 | 44 | void Body(int from, int to) 45 | { 46 | var vals = field.Values; 47 | 48 | for (int i = from; i < to; i++) 49 | vals[i] = other.ValueAt(field.PointAt(i)); 50 | } 51 | } 52 | 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | public static void Sample(this ISampledField2d field, IField2d other, Func converter, bool parallel = false) 64 | { 65 | if (parallel) 66 | Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); 67 | else 68 | Body(0, field.Count); 69 | 70 | void Body(int from, int to) 71 | { 72 | var vals = field.Values; 73 | 74 | for (int i = from; i < to; i++) 75 | vals[i] = converter(other.ValueAt(field.PointAt(i))); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Extensions/ISampledField3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Threading.Tasks; 9 | 10 | namespace SpatialSlur.Fields 11 | { 12 | /// 13 | /// 14 | /// 15 | public static class ISampledField3dExtensions 16 | { 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static ISampledField3d Duplicate(this ISampledField3d field) 24 | where T : struct 25 | { 26 | return field.Duplicate(true); 27 | } 28 | 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public static void Sample(this ISampledField3d field, IField3d other, bool parallel = false) 38 | { 39 | if (parallel) 40 | Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); 41 | else 42 | Body(0, field.Count); 43 | 44 | void Body(int from, int to) 45 | { 46 | var vals = field.Values; 47 | 48 | for (int i = from; i < to; i++) 49 | vals[i] = other.ValueAt(field.PointAt(i)); 50 | } 51 | } 52 | 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | public static void Sample(this ISampledField3d field, IField3d other, Func converter, bool parallel = false) 64 | { 65 | if (parallel) 66 | Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); 67 | else 68 | Body(0, field.Count); 69 | 70 | void Body(int from, int to) 71 | { 72 | var vals = field.Values; 73 | 74 | for (int i = from; i < to; i++) 75 | vals[i] = converter(other.ValueAt(field.PointAt(i))); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Extensions/ListExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | using SpatialSlur.Fields; 8 | 9 | namespace SpatialSlur 10 | { 11 | /// 12 | /// 13 | /// 14 | public static partial class ListExtensions 15 | { 16 | #region List> 17 | 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static void Add(this List> objects, Vector3d point, T value, double influence = 1.0) 27 | { 28 | objects.Add(IDWPoint3d.Create(point, value, influence)); 29 | } 30 | 31 | #endregion 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Field2d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// 12 | /// 13 | public static class Field2d 14 | { 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static IField2d Create(Func valueAt) 22 | { 23 | return new FuncField2d(valueAt); 24 | } 25 | 26 | 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static IField2d CreateTransformed(IField2d other, Transform2d transform) 35 | { 36 | transform.Invert(); 37 | return Create(p => other.ValueAt(transform.Apply(p))); 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/FuncField2d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | using SpatialSlur; 9 | 10 | namespace SpatialSlur.Fields 11 | { 12 | /// 13 | /// 14 | /// 15 | /// 16 | public class FuncField2d : IField2d, IField3d 17 | { 18 | /// 19 | public readonly Func ValueAt; 20 | 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | internal FuncField2d(Func valueAt) 27 | { 28 | ValueAt = valueAt ?? throw new ArgumentNullException(); 29 | } 30 | 31 | 32 | #region Explicit Interface Implementations 33 | 34 | T IField2d.ValueAt(Vector2d point) 35 | { 36 | return ValueAt(point); 37 | } 38 | 39 | 40 | T IField3d.ValueAt(Vector3d point) 41 | { 42 | return ValueAt(point.XY); 43 | } 44 | 45 | #endregion 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/FuncField3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// 12 | /// 13 | /// 14 | public class FuncField3d: IField2d, IField3d 15 | { 16 | /// 17 | public readonly Func ValueAt; 18 | 19 | 20 | /// 21 | /// 22 | /// 23 | /// 24 | internal FuncField3d(Func valueAt) 25 | { 26 | ValueAt = valueAt ?? throw new ArgumentNullException(); 27 | } 28 | 29 | 30 | #region Explicit Interface Implementations 31 | 32 | T IField2d.ValueAt(Vector2d point) 33 | { 34 | return ValueAt(point.As3d); 35 | } 36 | 37 | 38 | T IField3d.ValueAt(Vector3d point) 39 | { 40 | return ValueAt(point); 41 | } 42 | 43 | #endregion 44 | } 45 | } -------------------------------------------------------------------------------- /SpatialSlur/Fields/Grid.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace SpatialSlur.Fields 13 | { 14 | /// 15 | /// 16 | /// 17 | internal static class Grid 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static Func GetWrapFunction(WrapMode mode) 25 | { 26 | switch (mode) 27 | { 28 | case WrapMode.Clamp: 29 | return Clamp; 30 | case WrapMode.Repeat: 31 | return Repeat; 32 | case WrapMode.Mirror: 33 | return Mirror; 34 | } 35 | 36 | throw new NotSupportedException(); 37 | } 38 | 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | public static int Wrap(int index, int count, WrapMode mode) 48 | { 49 | return 50 | mode == WrapMode.Mirror ? Mirror(index, count) : 51 | mode == WrapMode.Repeat ? Repeat(index, count) : 52 | Clamp(index, count); 53 | 54 | #if OBSOLETE 55 | // switch implementation doesn't allow for inline optimization 56 | switch (mode) 57 | { 58 | case WrapMode.Clamp: 59 | return Clamp(index, range); 60 | case WrapMode.Repeat: 61 | return Repeat(index, range); 62 | case WrapMode.Mirror: 63 | return Mirror(index, range); 64 | } 65 | 66 | throw new NotSupportedException(); 67 | #endif 68 | } 69 | 70 | 71 | /// 72 | /// 73 | /// 74 | private static int Clamp(int i, int n) 75 | { 76 | return (i < 0) ? 0 : (i < n) ? i : n - 1; 77 | } 78 | 79 | 80 | /// 81 | /// 82 | /// 83 | private static int Repeat(int i, int n) 84 | { 85 | i %= n; 86 | return (i < 0) ? i + n : i; 87 | } 88 | 89 | 90 | /// 91 | /// 92 | /// 93 | private static int Mirror(int i, int n) 94 | { 95 | int n2 = n << 1; 96 | i %= n2; 97 | i = (i < 0) ? i + n2 : i; 98 | return n - Math.Abs(i - n); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/GridPoint2d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// Barycentric representation of position in a two-dimensional grid. 12 | /// 13 | [Serializable] 14 | public struct GridPoint2d 15 | { 16 | /// 17 | public double Weight0; 18 | /// 19 | public int Index0; 20 | 21 | /// 22 | public double Weight1; 23 | /// 24 | public int Index1; 25 | 26 | /// 27 | public double Weight2; 28 | /// 29 | public int Index2; 30 | 31 | /// 32 | public double Weight3; 33 | /// 34 | public int Index3; 35 | 36 | 37 | /// 38 | /// Assumes components of the given point are between 0 and 1 inclusive. 39 | /// 40 | /// 41 | public void SetWeights(Vector2d point) 42 | { 43 | (var u0, var v0) = point; 44 | 45 | double u1 = 1.0 - u0; 46 | double v1 = 1.0 - v0; 47 | 48 | Weight0 = u1 * v1; 49 | Weight1 = u0 * v1; 50 | Weight2 = u1 * v0; 51 | Weight3 = u0 * v0; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/GridPoint3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur; 8 | 9 | namespace SpatialSlur.Fields 10 | { 11 | /// 12 | /// Barycentric representation of position in a three-dimensional grid. 13 | /// 14 | [Serializable] 15 | public struct GridPoint3d 16 | { 17 | /// 18 | public double Weight0; 19 | /// 20 | public int Index0; 21 | 22 | /// 23 | public double Weight1; 24 | /// 25 | public int Index1; 26 | 27 | /// 28 | public double Weight2; 29 | /// 30 | public int Index2; 31 | 32 | /// 33 | public double Weight3; 34 | /// 35 | public int Index3; 36 | 37 | /// 38 | public double Weight4; 39 | /// 40 | public int Index4; 41 | 42 | /// 43 | public double Weight5; 44 | /// 45 | public int Index5; 46 | 47 | /// 48 | public double Weight6; 49 | /// 50 | public int Index6; 51 | 52 | /// 53 | public double Weight7; 54 | /// 55 | public int Index7; 56 | 57 | 58 | /// 59 | /// 60 | /// 61 | /// 62 | public void SetWeights(Vector3d point) 63 | { 64 | (var u0, var v0, var w0) = point; 65 | 66 | double u1 = 1.0 - u0; 67 | double v1 = 1.0 - v0; 68 | double w1 = 1.0 - w0; 69 | 70 | Weight0 = u1 * v1 * w1; 71 | Weight1 = u0 * v1 * w1; 72 | Weight2 = u1 * v0 * w1; 73 | Weight3 = u0 * v0 * w1; 74 | 75 | Weight4 = u1 * v1 * w0; 76 | Weight5 = u0 * v1 * w0; 77 | Weight6 = u1 * v0 * w0; 78 | Weight7 = u0 * v0 * w0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/IDWFieldFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Linq; 8 | 9 | using SpatialSlur; 10 | 11 | using D = SpatialSlur.SlurMath.Constantsd; 12 | 13 | namespace SpatialSlur.Fields 14 | { 15 | /// 16 | /// 17 | /// 18 | public abstract class IDWFieldFactory 19 | { 20 | /// 21 | /// 22 | /// 23 | /// 24 | public abstract IDWField3d Create(double power, double epsilon = D.ZeroTolerance); 25 | 26 | 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public IDWField3d CreateCopy(IDWField3d other) 33 | { 34 | var result = Create(other.Power, other.Epsilon); 35 | result.Objects.AddRange(other.Objects.Select(obj => obj.Duplicate())); 36 | return result; 37 | } 38 | 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | public IDWField3d CreateCopy(IDWField3d other, Func converter) 48 | { 49 | var result = Create(other.Power, other.Epsilon); 50 | result.Objects.AddRange(other.Objects.Select(obj => obj.Convert(converter))); 51 | return result; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/IDWObject3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | using SpatialSlur; 13 | 14 | namespace SpatialSlur.Fields 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | public abstract class IDWObject3d 21 | { 22 | private T _value; 23 | private double _influence; 24 | 25 | 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | public abstract double DistanceTo(Vector3d point); 32 | 33 | 34 | /// 35 | /// 36 | /// 37 | public T Value 38 | { 39 | get => _value; 40 | set => _value = value; 41 | } 42 | 43 | 44 | /// 45 | /// 46 | /// 47 | public double Influence 48 | { 49 | get => _influence; 50 | set => _influence = value; 51 | } 52 | 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | public abstract IDWObject3d Duplicate(); 59 | 60 | 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// 66 | public abstract IDWObject3d Convert(Func converter); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/IField2d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using SpatialSlur; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// Interface for a spatially varying function in 2 dimensions. 12 | /// 13 | /// 14 | public interface IField2d 15 | { 16 | /// 17 | /// Returns the value at the given point. 18 | /// 19 | /// 20 | /// 21 | T ValueAt(Vector2d point); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/IField3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using SpatialSlur; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// Interface for a spatially varying function in 3 dimensions. 12 | /// 13 | public interface IField3d 14 | { 15 | /// 16 | /// Returns the value at the given point. 17 | /// 18 | /// 19 | /// 20 | T ValueAt(Vector3d point); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/IGradient2d.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | /* 4 | * Notes 5 | */ 6 | 7 | using SpatialSlur; 8 | 9 | namespace SpatialSlur.Fields 10 | { 11 | /// 12 | /// 13 | /// 14 | /// 15 | public interface IGradient2d 16 | { 17 | /// 18 | /// Returns the the gradient at the given point. 19 | /// 20 | /// 21 | /// 22 | /// 23 | void GradientAt(Vector2d point, out T dx, out T dy); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/IGradient3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using SpatialSlur; 7 | 8 | namespace SpatialSlur.Fields 9 | { 10 | /// 11 | /// 12 | /// 13 | /// 14 | public interface IGradient3d 15 | { 16 | /// 17 | /// Returns the the gradient at the given point. 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | void GradientAt(Vector3d point, out T dx, out T dy, out T dz); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/ISampledField.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | using SpatialSlur.Collections; 6 | 7 | namespace SpatialSlur.Fields 8 | { 9 | /// 10 | /// 11 | /// 12 | public interface ISampledField 13 | { 14 | /// 15 | /// Returns the field's array of sample values. 16 | /// 17 | ArrayView Values { get; } 18 | 19 | 20 | /// 21 | /// Returns the number of samples in the field. 22 | /// 23 | int Count { get; } 24 | 25 | 26 | /// 27 | /// Returns a copy of this field. 28 | /// Note that that value array of the returned field is a deep copy but other fields may be shallow depending on the implementation. 29 | /// 30 | /// 31 | ISampledField Duplicate(bool setValues); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/ISampledField2d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | 8 | using SpatialSlur; 9 | 10 | namespace SpatialSlur.Fields 11 | { 12 | /// 13 | /// 14 | /// 15 | public interface ISampledField2d : ISampledField, IField2d 16 | { 17 | /// 18 | /// Returns all sample points used by this field. 19 | /// 20 | IEnumerable Points { get; } 21 | 22 | 23 | /// 24 | /// Returns the sample point at the given index. 25 | /// 26 | /// 27 | /// 28 | Vector2d PointAt(int index); 29 | 30 | 31 | /// 32 | /// Returns a copy of this field. 33 | /// Note that that sample value array of the returned field is a deep copy but other fields may be shallow depending on the implementation. 34 | /// 35 | /// 36 | new ISampledField2d Duplicate(bool setValues); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/Interfaces/ISampledField3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | 8 | using SpatialSlur; 9 | 10 | namespace SpatialSlur.Fields 11 | { 12 | /// 13 | /// 14 | /// 15 | public interface ISampledField3d : ISampledField, IField3d 16 | { 17 | /// 18 | /// Returns all sample points used by this field. 19 | /// 20 | IEnumerable Points { get; } 21 | 22 | 23 | /// 24 | /// Returns the sample point at the given index. 25 | /// 26 | /// 27 | /// 28 | Vector3d PointAt(int index); 29 | 30 | 31 | /// 32 | /// Returns a copy of this field. 33 | /// Note that that sample value array of the returned field is a deep copy but other fields may be shallow depending on the implementation. 34 | /// 35 | /// 36 | new ISampledField3d Duplicate(bool setValues); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SpatialSlur/Fields/MeshField3dFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using SpatialSlur.Meshes; 10 | 11 | namespace SpatialSlur.Fields 12 | { 13 | /// 14 | /// 15 | /// 16 | public abstract class MeshField3dFactory 17 | where T : struct 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public abstract MeshField3d Create(HeMesh3d mesh); 25 | 26 | 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public abstract MeshField3d Create(MeshField3d other); 33 | 34 | 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | public MeshField3d CreateCopy(MeshField3d other) 41 | { 42 | var result = Create(other); 43 | result.Set(other); 44 | return result; 45 | } 46 | 47 | 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | /// 56 | public MeshField3d CreateCopy(MeshField3d other, Func converter, bool parallel = false) 57 | where U : struct 58 | { 59 | var result = Create(other); 60 | other.Convert(converter, result, parallel); 61 | return result; 62 | } 63 | } 64 | } 65 | 66 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Delegates.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | 8 | namespace SpatialSlur.Meshes 9 | { 10 | /// 11 | /// 12 | /// 13 | internal static partial class Delegates 14 | { 15 | /// 16 | /// 17 | /// 18 | /// 19 | internal static class Position3d 20 | where T : IPosition3d 21 | { 22 | /// 23 | /// 24 | /// 25 | public static readonly Func Get = t => t.Position; 26 | 27 | /// 28 | /// 29 | /// 30 | public static readonly Action Set = (t, p) => t.Position = p; 31 | } 32 | 33 | 34 | /// 35 | /// 36 | /// 37 | /// 38 | internal static class Normal3d 39 | where T : INormal3d 40 | { 41 | /// 42 | /// 43 | /// 44 | public static readonly Func Get = t => t.Normal; 45 | 46 | /// 47 | /// 48 | /// 49 | public static readonly Action Set = (t, n) => t.Normal = n; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Enums/SmoothBoundaryType.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Meshes 7 | { 8 | /// 9 | /// Enum of boundary types for smoothing. 10 | /// 11 | public enum SmoothBoundaryType 12 | { 13 | /// All boundary vertices are fixed. 14 | Fixed, 15 | /// Only degree 2 boundary vertices are fixed. 16 | CornerFixed, 17 | /// Boundary vertices are free. 18 | Free 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/HeGraph3dFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using SpatialSlur; 9 | using SpatialSlur.Meshes.Impl; 10 | 11 | using D = SpatialSlur.SlurMath.Constantsd; 12 | 13 | namespace SpatialSlur.Meshes 14 | { 15 | using G = HeGraph3d; 16 | using V = HeGraph3d.Vertex; 17 | using E = HeGraph3d.Halfedge; 18 | 19 | /// 20 | /// 21 | /// 22 | [Serializable] 23 | public class HeGraph3dFactory : HeGraphFactory 24 | { 25 | /// 26 | public sealed override G Create(int vertexCapacity, int hedgeCapacity) 27 | { 28 | return new G(vertexCapacity, hedgeCapacity); 29 | } 30 | 31 | 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | public G CreateFromLineSegments(IReadOnlyList endPoints, double tolerance = D.ZeroTolerance, bool allowMultiEdges = false, bool allowLoops = false) 41 | { 42 | return CreateFromLineSegments(endPoints, (v, p) => v.Position = p, tolerance, allowMultiEdges, allowLoops); 43 | } 44 | 45 | 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | public G CreateFromVertexTopology(HeMesh mesh) 52 | { 53 | var graph = Create(mesh.Vertices.Count, mesh.Halfedges.Count); 54 | graph.AppendVertexTopology(mesh); 55 | return graph; 56 | } 57 | 58 | 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | public G CreateFromFaceTopology(HeMesh mesh) 65 | { 66 | var graph = Create(mesh.Faces.Count, mesh.Halfedges.Count); 67 | graph.AppendFaceTopology(mesh); 68 | return graph; 69 | } 70 | 71 | 72 | /// 73 | /// 74 | /// 75 | /// 76 | /// 77 | public G CreateFromJson(string path) 78 | { 79 | var result = Create(); 80 | Interop.Meshes.ReadFromJson(path, result); 81 | return result; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/HeGraphFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur.Meshes.Impl; 8 | 9 | namespace SpatialSlur.Meshes 10 | { 11 | using G = HeGraph; 12 | using V = HeGraph.Vertex; 13 | using E = HeGraph.Halfedge; 14 | 15 | /// 16 | /// 17 | /// 18 | [Serializable] 19 | public class HeGraphFactory : HeGraphFactory 20 | { 21 | /// 22 | public sealed override G Create(int vertexCapacity, int hedgeCapacity) 23 | { 24 | return new G(vertexCapacity, hedgeCapacity); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/HeMesh3dFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using SpatialSlur; 9 | using SpatialSlur.Meshes.Impl; 10 | 11 | using D = SpatialSlur.SlurMath.Constantsd; 12 | 13 | namespace SpatialSlur.Meshes 14 | { 15 | using M = HeMesh3d; 16 | using V = HeMesh3d.Vertex; 17 | using E = HeMesh3d.Halfedge; 18 | using F = HeMesh3d.Face; 19 | 20 | /// 21 | /// 22 | /// 23 | [Serializable] 24 | public class HeMesh3dFactory : HeMeshFactory 25 | { 26 | /// 27 | public sealed override M Create(int vertexCapacity, int halfedgeCapacity, int faceCapacity) 28 | { 29 | return new M(vertexCapacity, halfedgeCapacity, faceCapacity); 30 | } 31 | 32 | 33 | /// 34 | /// 35 | /// 36 | /// 37 | public M CreateFromFaceVertexData(IEnumerable vertices, IEnumerable faces) 38 | where T : IEnumerable 39 | { 40 | return CreateFromFaceVertexData(vertices, faces, (v, p) => v.Position = p); 41 | } 42 | 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | public M CreateFromPolygons(IEnumerable polygons, double tolerance = D.ZeroTolerance) 49 | where T : IEnumerable 50 | { 51 | return CreateFromPolygons(polygons, (v, p) => v.Position = p, tolerance); 52 | } 53 | 54 | 55 | /// 56 | /// 57 | /// 58 | /// 59 | public M CreateFromOBJ(string path) 60 | { 61 | return CreateFromObj(path, (v, p) => v.Position = p); 62 | } 63 | 64 | 65 | /// 66 | /// 67 | /// 68 | /// 69 | /// 70 | public M CreateFromJson(string path) 71 | { 72 | var result = Create(); 73 | Interop.Meshes.ReadFromJson(path, result); 74 | return result; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/HeMeshFactory.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur.Meshes.Impl; 8 | 9 | namespace SpatialSlur.Meshes 10 | { 11 | using M = HeMesh; 12 | using V = HeMesh.Vertex; 13 | using E = HeMesh.Halfedge; 14 | using F = HeMesh.Face; 15 | 16 | /// 17 | /// 18 | /// 19 | [Serializable] 20 | public class HeMeshFactory : HeMeshFactory 21 | { 22 | /// 23 | public sealed override M Create(int vertexCapacity, int hedgeCapacity, int faceCapacity) 24 | { 25 | return new M(vertexCapacity, hedgeCapacity, faceCapacity); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Interfaces/IFaceQuadrangulator.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | using SpatialSlur.Meshes.Impl; 8 | 9 | namespace SpatialSlur.Meshes 10 | { 11 | /// 12 | /// 13 | /// 14 | public interface IFaceQuadrangulator 15 | { 16 | /// 17 | /// Iterates through each quad in the face of the given halfedge. 18 | /// The last 2 vertices from each quad must not belong to the previously returned quad. 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | IEnumerable<(V, V, V, V)> GetQuads(HeMesh.Halfedge start) 26 | where V : HeMesh.Vertex 27 | where E : HeMesh.Halfedge 28 | where F : HeMesh.Face; 29 | 30 | 31 | /// 32 | /// Splits the face of the given halfedge into quads. 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | void Quadrangulate(HeMesh mesh, E start) 40 | where V : HeMesh.Vertex 41 | where E : HeMesh.Halfedge 42 | where F : HeMesh.Face; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Interfaces/IFaceTriangulator.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System.Collections.Generic; 7 | using SpatialSlur.Meshes.Impl; 8 | 9 | namespace SpatialSlur.Meshes 10 | { 11 | /// 12 | /// 13 | /// 14 | public interface IFaceTriangulator 15 | { 16 | /// 17 | /// Iterates through each triangle in the face of the given halfedge. 18 | /// The last vertex from each triangle must not belong to the previously returned triangle. 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | IEnumerable<(V, V, V)> GetTriangles(HeMesh.Halfedge start) 26 | where V : HeMesh.Vertex 27 | where E : HeMesh.Halfedge 28 | where F : HeMesh.Face; 29 | 30 | 31 | /// 32 | /// Splits the face of the given halfedge into triangles. 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | void Triangulate(HeMesh mesh, E start) 40 | where V : HeMesh.Vertex 41 | where E : HeMesh.Halfedge 42 | where F : HeMesh.Face; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Interfaces/INormal3d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using SpatialSlur; 4 | 5 | /* 6 | * Notes 7 | */ 8 | 9 | namespace SpatialSlur.Meshes 10 | { 11 | /// 12 | /// 13 | /// 14 | public interface INormal3d 15 | { 16 | /// 17 | Vector3d Normal { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/Interfaces/IPosition3d.cs: -------------------------------------------------------------------------------- 1 |  2 | using SpatialSlur; 3 | 4 | /* 5 | * Notes 6 | */ 7 | 8 | namespace SpatialSlur.Meshes 9 | { 10 | /// 11 | /// 12 | /// 13 | public interface IPosition3d 14 | { 15 | /// 16 | Vector3d Position { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/TriMesh3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Meshes 7 | { 8 | /// 9 | /// 10 | /// 11 | public class TriMesh3d : TriMesh 12 | { 13 | /// 14 | /// 15 | /// 16 | public TriMesh3d() 17 | { 18 | } 19 | 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public TriMesh3d(int vertexCount, int faceCount) 27 | : base(vertexCount, faceCount) 28 | { 29 | } 30 | 31 | 32 | /// 33 | /// 34 | /// 35 | /// 36 | public TriMesh3d(TriMesh3d other) 37 | : base(other) 38 | { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SpatialSlur/Meshes/TriMesh3f.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | namespace SpatialSlur.Meshes 7 | { 8 | /// 9 | /// 10 | /// 11 | public class TriMesh3f : TriMesh 12 | { 13 | /// 14 | /// 15 | /// 16 | public TriMesh3f() 17 | { 18 | } 19 | 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public TriMesh3f(int vertexCount, int faceCount) 27 | : base(vertexCount, faceCount) 28 | { 29 | } 30 | 31 | 32 | /// 33 | /// 34 | /// 35 | /// 36 | public TriMesh3f(TriMesh3f other) 37 | : base(other) 38 | { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SpatialSlur/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SpatialSlur")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SpatialSlur")] 13 | [assembly: AssemblyCopyright("Copyright © David Reeves 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("11db2625-f1c7-4fca-a7d3-f8ac93f99c8a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | // [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyVersion(SpatialSlur.AssemblyInfo.VersionNumber)] 37 | 38 | // Expose internals 39 | //[assembly: InternalsVisibleTo("SlurGH")] 40 | //[assembly: InternalsVisibleTo("Examples")] 41 | 42 | namespace SpatialSlur 43 | { 44 | /// 45 | /// 46 | /// 47 | public static class AssemblyInfo 48 | { 49 | /// 50 | public const string VersionNumber = "0.3.1.*"; 51 | } 52 | } -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/ArrayViewExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | using SpatialSlur.Collections; 14 | 15 | namespace SpatialSlur.Rhino 16 | { 17 | /// 18 | /// 19 | /// 20 | public static class ArrayViewExtensions 21 | { 22 | /// 23 | /// Workaround for lack of support for ref returns in Grasshopper script components 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | public static T Get(this ArrayView view, int index) 30 | { 31 | return view[index]; 32 | } 33 | 34 | 35 | /// 36 | /// Workaround for lack of support for ref returns in Grasshopper script components 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | public static void Set(this ArrayView view, int index, T item) 43 | { 44 | view[index] = item; 45 | } 46 | } 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/BoundingBoxExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using Rhino.Geometry; 9 | using SpatialSlur; 10 | 11 | namespace SpatialSlur.Rhino 12 | { 13 | /// 14 | /// 15 | /// 16 | public static class BoundingBoxExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static Interval2d ToInterval2d(this BoundingBox bbox) 24 | { 25 | Vector3d p0 = bbox.Min; 26 | Vector3d p1 = bbox.Max; 27 | return new Interval2d(p0.XY, p1.XY); 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | public static Interval3d ToInterval3d(this BoundingBox bbox) 37 | { 38 | return new Interval3d(bbox.Min, bbox.Max); 39 | } 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/GridField3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System.Collections.Generic; 9 | 10 | using Rhino.Geometry; 11 | using SpatialSlur; 12 | using SpatialSlur.Fields; 13 | 14 | namespace SpatialSlur.Rhino 15 | { 16 | /// 17 | /// 18 | /// 19 | public static class GridField3dExtensions 20 | { 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static Mesh ToPolySoup(this Grid3d field, IEnumerable selection) 28 | { 29 | var mesh = new Mesh(); 30 | var verts = mesh.Vertices; 31 | var faces = mesh.Faces; 32 | 33 | (var dx, var dy) = (field.Scale.XY * 0.5); 34 | 35 | // add vertices 36 | foreach (int index in selection) 37 | { 38 | (var x, var y, var z) = field.ToWorldSpace(index); 39 | verts.Add(x - dx, y - dy, z); 40 | verts.Add(x + dx, y - dy, z); 41 | verts.Add(x - dx, y + dy, z); 42 | verts.Add(x + dx, y + dy, z); 43 | } 44 | 45 | // add faces 46 | for (int i = 0; i < verts.Count; i += 4) 47 | faces.AddFace(i, i + 1, i + 3, i + 2); 48 | 49 | return mesh; 50 | } 51 | } 52 | } 53 | 54 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/HeStructureExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System.Collections.Concurrent; 9 | using System.Threading.Tasks; 10 | 11 | using Rhino.Geometry; 12 | using SpatialSlur.Meshes; 13 | using SpatialSlur.Meshes.Impl; 14 | 15 | namespace SpatialSlur.Rhino 16 | { 17 | /// 18 | /// 19 | /// 20 | public static class HeStructureExtensions 21 | { 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | public static void Transform(this HeStructure graph, Transform xform, bool parallel = false) 31 | where V : HeStructure.Vertex, IPosition3d 32 | where E : HeStructure.Halfedge 33 | { 34 | var verts = graph.Vertices; 35 | 36 | if (parallel) 37 | Parallel.ForEach(Partitioner.Create(0, verts.Count), range => Body(range.Item1, range.Item2)); 38 | else 39 | Body(0, verts.Count); 40 | 41 | void Body(int from, int to) 42 | { 43 | for (int i = from; i < to; i++) 44 | { 45 | var v = verts[i]; 46 | v.Position = xform.ApplyToPoint(v.Position); 47 | } 48 | } 49 | } 50 | 51 | 52 | /// 53 | /// 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | public static void SpaceMorph(this HeStructure graph, SpaceMorph xmorph, bool parallel = false) 61 | where V : HeStructure.Vertex, IPosition3d 62 | where E : HeStructure.Halfedge 63 | { 64 | var verts = graph.Vertices; 65 | 66 | if (parallel) 67 | Parallel.ForEach(Partitioner.Create(0, verts.Count), range => Body(range.Item1, range.Item2)); 68 | else 69 | Body(0, verts.Count); 70 | 71 | void Body(int from, int to) 72 | { 73 | for (int i = from; i < to; i++) 74 | { 75 | var v = verts[i]; 76 | v.Position = xmorph.MorphPoint(v.Position); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/ISampledField3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using System.Collections.Concurrent; 10 | using System.Linq; 11 | using System.Threading.Tasks; 12 | using System.Drawing; 13 | 14 | using Rhino.Geometry; 15 | using SpatialSlur.Fields; 16 | 17 | namespace SpatialSlur.Rhino 18 | { 19 | /// 20 | /// 21 | /// 22 | public static class ISampledField3dExtensions 23 | { 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | public static PointCloud ToPointCloud(this ISampledField3d field, Func getColor, bool parallel = false) 33 | where T : struct 34 | { 35 | var cloud = new PointCloud(field.Points.Select(p => new Point3d(p.X, p.Y, 0.0))); 36 | 37 | if (parallel) 38 | Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); 39 | else 40 | Body(0, field.Count); 41 | 42 | void Body(int from, int to) 43 | { 44 | var vals = field.Values; 45 | 46 | for (int i = from; i < to; i++) 47 | cloud[i].Color = getColor(vals[i]); 48 | } 49 | 50 | return cloud; 51 | } 52 | } 53 | } 54 | 55 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/Interval2dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using Rhino.Geometry; 9 | using SpatialSlur; 10 | 11 | namespace SpatialSlur.Rhino 12 | { 13 | /// 14 | /// 15 | /// 16 | public static partial class Interval2dExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static BoundingBox ToBoundingBox(this Interval2d interval) 24 | { 25 | var x = interval.X; 26 | var y = interval.Y; 27 | return new BoundingBox(x.A, y.A, 0.0, x.B, y.B, 0.0); 28 | } 29 | } 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/Interval3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using Rhino.Geometry; 9 | using SpatialSlur; 10 | 11 | namespace SpatialSlur.Rhino 12 | { 13 | /// 14 | /// 15 | /// 16 | public static partial class Interval3dExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static BoundingBox ToBoundingBox(this Interval3d interval) 24 | { 25 | var x = interval.X; 26 | var y = interval.Y; 27 | var z = interval.Z; 28 | return new BoundingBox(x.A, y.A, z.A, x.B, y.B, z.B); 29 | } 30 | } 31 | } 32 | 33 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/LineExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Rhino 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class LineExtensions 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static Interval3d ToInterval3d(this Line line) 25 | { 26 | return new Interval3d(line.From, line.To); 27 | } 28 | } 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/Orient3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using Rhino.Geometry; 9 | using SpatialSlur; 10 | 11 | using Vec3d = Rhino.Geometry.Vector3d; 12 | 13 | namespace SpatialSlur.Rhino 14 | { 15 | /// 16 | /// 17 | /// 18 | public static partial class Orient3dExtensions 19 | { 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static Plane ToPlane(this Orient3d orient) 26 | { 27 | return new Plane( 28 | orient.Translation, 29 | orient.Rotation.X, 30 | (Vec3d)orient.Rotation.Y 31 | ); 32 | } 33 | } 34 | } 35 | 36 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/PlaneExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Rhino 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class PlaneExtensions 18 | { 19 | /// 20 | /// Returns the transformation matrix defined by this plane. 21 | /// 22 | /// 23 | /// 24 | public static Transform ToTransform(this Plane plane) 25 | { 26 | return RhinoFactory.Transform.CreateFromPlane(plane); 27 | } 28 | 29 | 30 | /// 31 | /// Returns the inverse of the transformation matrix defined by this plane. 32 | /// 33 | /// 34 | /// 35 | public static Transform ToTransformInverse(this Plane plane) 36 | { 37 | return RhinoFactory.Transform.CreateInverseFromPlane(plane); 38 | } 39 | 40 | 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | public static Orient3d ToOrient3d(this Plane plane) 47 | { 48 | return new Orient3d(OrthoBasis3d.CreateFromXY(plane.XAxis, plane.YAxis), plane.Origin); 49 | } 50 | } 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/Point3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Rhino 12 | { 13 | /// 14 | /// 15 | /// 16 | public static class Point3dExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static Point3d LerpTo(this Point3d point, Point3d other, double factor) 26 | { 27 | return point + (other - point) * factor; 28 | } 29 | 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public static double SquareDistanceTo(this Point3d point, Point3d other) 38 | { 39 | Vector3d v = other - point; 40 | return v.SquareLength; 41 | } 42 | } 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/PriorityQueueExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | 10 | using SpatialSlur.Collections; 11 | 12 | namespace SpatialSlur.Rhino 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class PriorityQueueExtensions 18 | { 19 | /// 20 | /// Workaround for lack of support for ValueTuple in Grasshopper script components 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static void GetMin(this PriorityQueue queue, out K key, out V value) 28 | where K : IComparable 29 | { 30 | (key, value) = queue.Min; 31 | } 32 | 33 | 34 | /// 35 | /// Workaround for lack of support for ValueTuple in Grasshopper script components 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | public static void RemoveMin(this PriorityQueue queue, out K key, out V value) 43 | where K : IComparable 44 | { 45 | (key, value) = queue.RemoveMin(); 46 | } 47 | } 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/QuadStripExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using System.Collections.Concurrent; 10 | using System.Drawing; 11 | 12 | using Rhino.Geometry; 13 | using SpatialSlur.Meshes; 14 | using SpatialSlur.Meshes.Impl; 15 | 16 | using Vec3d = Rhino.Geometry.Vector3d; 17 | using Vec3f = Rhino.Geometry.Vector3f; 18 | 19 | namespace SpatialSlur.Rhino 20 | { 21 | /// 22 | /// 23 | /// 24 | public static class QuadStripExtensions 25 | { 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static Mesh ToMesh(this QuadStrip strip) 35 | where V : HeMesh.Vertex, IPosition3d 36 | where E : HeMesh.Halfedge 37 | where F : HeMesh.Face 38 | { 39 | return ToMesh(strip, v => v.Position.As3f); 40 | } 41 | 42 | 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | public static Mesh ToMesh(this QuadStrip strip, Func getPosition, Func getNormal = null, Func getTexture = null, Func getColor = null) 56 | where V : HeMesh.Vertex 57 | where E : HeMesh.Halfedge 58 | where F : HeMesh.Face 59 | { 60 | return RhinoFactory.Mesh.CreateFromQuadStrip(strip, getPosition, getNormal, getTexture, getColor); 61 | } 62 | } 63 | } 64 | 65 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/TransformExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Rhino 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class TransformExtensions 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static Vector4d Apply(this Transform xform, Vector4d vector) 24 | { 25 | return new Vector4d( 26 | vector.X * xform.M00 + vector.Y * xform.M01 + vector.Z * xform.M02 + vector.W * xform.M03, 27 | vector.X * xform.M10 + vector.Y * xform.M11 + vector.Z * xform.M12 + vector.W * xform.M13, 28 | vector.X * xform.M20 + vector.Y * xform.M21 + vector.Z * xform.M22 + vector.W * xform.M23, 29 | vector.W 30 | ); 31 | } 32 | 33 | 34 | /// 35 | /// 36 | /// 37 | /// 38 | public static Vector3d Apply(this Transform xform, Vector3d vector) 39 | { 40 | return new Vector3d( 41 | vector.X * xform.M00 + vector.Y * xform.M01 + vector.Z * xform.M02, 42 | vector.X * xform.M10 + vector.Y * xform.M11 + vector.Z * xform.M12, 43 | vector.X * xform.M20 + vector.Y * xform.M21 + vector.Z * xform.M22 44 | ); 45 | } 46 | 47 | 48 | /// 49 | /// 50 | /// 51 | /// 52 | public static Vector3d ApplyToPoint(this Transform xform, Vector3d point) 53 | { 54 | return new Vector3d( 55 | point.X * xform.M00 + point.Y * xform.M01 + point.Z * xform.M02 + xform.M03, 56 | point.X * xform.M10 + point.Y * xform.M11 + point.Z * xform.M12 + xform.M13, 57 | point.X * xform.M20 + point.Y * xform.M21 + point.Z * xform.M22 + xform.M23 58 | ); 59 | } 60 | } 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Extensions/Vector3dExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | 9 | using Rhino.Geometry; 10 | 11 | namespace SpatialSlur.Rhino 12 | { 13 | /// 14 | /// 15 | /// 16 | public static class Vector3dExtensions 17 | { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static Vector3d LerpTo(this Vector3d vector, Vector3d other, double factor) 26 | { 27 | return vector + (other - vector) * factor; 28 | } 29 | } 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /SpatialSlur/Rhino/Field3d.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Fields 13 | { 14 | /// 15 | /// 16 | /// 17 | public static partial class Field3d 18 | { 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static IField3d CreateDistance(Mesh mesh) 25 | { 26 | return Create(p => p.DistanceTo(mesh.ClosestPoint(p))); 27 | } 28 | 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static IField3d CreateSignedDistance(Mesh mesh) 35 | { 36 | return Create(p => 37 | { 38 | var mp = mesh.ClosestMeshPoint(p, 0.0); 39 | var d = p - (Vector3d)mp.Point; 40 | return d.Length * Math.Sign(Vector3d.Dot(d, mesh.NormalAt(mp))); 41 | }); 42 | } 43 | 44 | 45 | /// 46 | /// 47 | /// 48 | /// 49 | public static IField3d CreateSignedPerpDistance(Mesh mesh) 50 | { 51 | return Create(p => 52 | { 53 | var mp = mesh.ClosestMeshPoint(p, 0.0); 54 | var n = mesh.NormalAt(mp); 55 | var m = n.SquareLength; 56 | return m > 0.0 ? Vector3d.Dot(p - (Vector3d)mp.Point, n) / Math.Sqrt(m) : 0.0; 57 | }); 58 | } 59 | } 60 | } 61 | 62 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/CurveFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Tools 13 | { 14 | /// 15 | /// 16 | /// 17 | [Serializable] 18 | public class CurveFeature : IFeature 19 | { 20 | private Curve _curve; 21 | 22 | 23 | /// 24 | /// 25 | /// 26 | /// 27 | public CurveFeature(Curve curve) 28 | { 29 | _curve = curve; 30 | } 31 | 32 | 33 | /// 34 | public int Rank 35 | { 36 | get { return 1; } 37 | } 38 | 39 | 40 | /// 41 | public Vector3d ClosestPoint(Vector3d point) 42 | { 43 | _curve.ClosestPoint(point, out double t); 44 | return _curve.PointAt(t); 45 | } 46 | } 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/ExtendedMeshFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using Rhino.Geometry; 10 | using SpatialSlur; 11 | 12 | namespace SpatialSlur.Tools 13 | { 14 | /// 15 | /// 16 | /// 17 | [Serializable] 18 | public class ExtendedMeshFeature : ISurfaceFeature 19 | { 20 | private Mesh _mesh; 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | public ExtendedMeshFeature(Mesh mesh) 27 | { 28 | _mesh = mesh; 29 | _mesh.Normals.ComputeNormals(); 30 | } 31 | 32 | 33 | /// 34 | public int Rank 35 | { 36 | get { return 2; } 37 | } 38 | 39 | 40 | /// 41 | public Vector3d ClosestPoint(Vector3d point) 42 | { 43 | var mp = _mesh.ClosestMeshPoint(point, 0.0); 44 | 45 | Vector3d cp = _mesh.PointAt(mp); 46 | Vector3d cn = _mesh.NormalAt(mp); 47 | return point + Vector3d.Project(cp - point, cn); 48 | } 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/IFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using SpatialSlur; 7 | 8 | namespace SpatialSlur.Tools 9 | { 10 | /// 11 | /// 12 | /// 13 | public interface IFeature 14 | { 15 | /// 16 | /// Determines priority during assignment 17 | /// 18 | int Rank { get; } 19 | 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | Vector3d ClosestPoint(Vector3d point); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/ISurfaceFeature.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Notes 3 | */ 4 | 5 | namespace SpatialSlur.Tools 6 | { 7 | /// 8 | /// Strongly typed interface for a subset of IFeatures 9 | /// 10 | public interface ISurfaceFeature : IFeature 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/MeshFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using System; 9 | using System.Linq; 10 | using System.Collections.Generic; 11 | using Rhino.Geometry; 12 | using SpatialSlur; 13 | 14 | namespace SpatialSlur.Tools 15 | { 16 | /// 17 | /// 18 | /// 19 | [Serializable] 20 | public class MeshFeature : ISurfaceFeature 21 | { 22 | private Mesh _mesh; 23 | 24 | 25 | /// 26 | /// 27 | /// 28 | /// 29 | public MeshFeature(Mesh mesh) 30 | { 31 | _mesh = mesh; 32 | } 33 | 34 | 35 | /// 36 | public int Rank 37 | { 38 | get { return 2; } 39 | } 40 | 41 | 42 | /// 43 | public Vector3d ClosestPoint(Vector3d point) 44 | { 45 | return _mesh.ClosestPoint(point); 46 | } 47 | } 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/PointCloudFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_RHINO 7 | 8 | using Rhino.Geometry; 9 | 10 | namespace SpatialSlur.Tools 11 | { 12 | /// 13 | /// 14 | /// 15 | public class PointCloudFeature : IFeature 16 | { 17 | private PointCloud _pointCloud; 18 | 19 | 20 | /// 21 | /// 22 | /// 23 | public PointCloudFeature(PointCloud pointCloud) 24 | { 25 | _pointCloud = pointCloud; 26 | } 27 | 28 | 29 | /// 30 | public int Rank 31 | { 32 | get { return 0; } 33 | } 34 | 35 | 36 | /// 37 | public Vector3d ClosestPoint(Vector3d point) 38 | { 39 | var index = _pointCloud.ClosestPoint(point); 40 | return _pointCloud[index].Location; 41 | } 42 | } 43 | } 44 | 45 | #endif -------------------------------------------------------------------------------- /SpatialSlur/Tools/Features/PointFeature.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | using System; 7 | using SpatialSlur; 8 | 9 | namespace SpatialSlur.Tools 10 | { 11 | /// 12 | /// 13 | /// 14 | [Serializable] 15 | public class PointFeature : IFeature 16 | { 17 | private Vector3d _point; 18 | 19 | 20 | /// 21 | /// 22 | /// 23 | /// 24 | public PointFeature(Vector3d point) 25 | { 26 | _point = point; 27 | } 28 | 29 | 30 | /// 31 | public int Rank 32 | { 33 | get { return 0; } 34 | } 35 | 36 | 37 | /// 38 | public Vector3d ClosestPoint(Vector3d point) 39 | { 40 | return _point; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SpatialSlur/Unity/Extensions/ArrayExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_UNITY 7 | 8 | using System; 9 | using UnityEngine; 10 | 11 | namespace SpatialSlur 12 | { 13 | /// 14 | /// 15 | /// 16 | public static partial class ArrayExtensions 17 | { 18 | #region Color[] 19 | 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static Color Lerp(this Color[] colors, float factor) 27 | { 28 | int last = colors.Length - 1; 29 | factor = SlurMath.Fract(factor * last, out int i); 30 | 31 | if (i < 0) 32 | return colors[0]; 33 | else if (i >= last) 34 | return colors[last]; 35 | 36 | return Color.LerpUnclamped(colors[i], colors[i + 1], factor); 37 | } 38 | 39 | #endregion 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /SpatialSlur/Unity/Extensions/IReadOnlyListExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Notes 4 | */ 5 | 6 | #if USING_UNITY 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | using UnityEngine; 11 | 12 | namespace SpatialSlur 13 | { 14 | /// 15 | /// 16 | /// 17 | public static partial class IReadOnlyListExtensions 18 | { 19 | #region IReadOnlyList 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static Color Lerp(this IReadOnlyList colors, float factor) 28 | { 29 | int last = colors.Count - 1; 30 | factor = SlurMath.Fract(factor * last, out int i); 31 | 32 | if (i < 0) 33 | return colors[0]; 34 | else if (i >= last) 35 | return colors[last]; 36 | 37 | return Color.LerpUnclamped(colors[i], colors[i + 1], factor); 38 | } 39 | 40 | #endregion 41 | } 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /SpatialSlur/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------