public Mesh Metaball(double iso) { this.use_iso = iso; Plane plane = new Plane(); Plane.FitPlaneToPoints(use_charges, out plane); plane.Origin = use_charges[0]; Interval xSize = new Interval(-use_radii[0], use_radii[0]); Box box = new Box(plane, xSize, xSize, xSize); int num27 = use_charges.Count - 1; for (int i = 1; i <= num27; i++) { plane.Origin = use_charges[i]; box.Union(plane.PointAt(-use_radii[i], -use_radii[i], -use_radii[i])); box.Union(plane.PointAt(use_radii[i], use_radii[i], use_radii[i])); } box.Inflate(res); int xSet = (int)Math.Round((double)(box.X.Length / res)); int ySet = (int)Math.Round((double)(box.Y.Length / res)); int zSet = (int)Math.Round((double)(box.Z.Length / res)); double xLength = box.X.Length / ((double)xSet); double yLength = box.Y.Length / ((double)ySet); double zLength = box.Z.Length / ((double)zSet); double xBase = xLength / 2.0; double yBase = yLength / 2.0; double zBase = zLength / 2.0; plane.Origin = box.GetCorners()[0]; List<Point3d> list = new List<Point3d>(); Mesh mesh = new Mesh(); for (int j = 0; j <= xSet - 1; j++) { for (int m = 0; m <= ySet - 1; m++) { for (int n = 0; n <= zSet - 1; n++) { Point3d item = plane.PointAt(xBase + (xLength * j), yBase + (yLength * m), zBase + (zLength * n)); int xSet1 = use_charges.Count - 1; for (int k = 0; k <= xSet1; k++) { if (item.DistanceTo(use_charges[k]) < (use_radii[k] + res)) { Plane pl = plane; pl.Origin = item; Mesh other = this.local_tet(pl, xBase, yBase, zBase); mesh.Append(other); list.Add(item); break; } } } } } mesh.Vertices.CombineIdentical(true, true); mesh.UnifyNormals(); return mesh; }
/// <summary> /// Aligned bounding box solver. Gets the world axis aligned bounding box for the transformed <paramref name="value"/>. /// </summary> /// <param name="value"></param> /// <param name="xform">Transformation to apply to <paramref name="value"/> prior to the BoundingBox computation. The <paramref name="value"/> itself is not modified</param> /// <returns>The accurate bounding box of the transformed geometry in world coordinates or <see cref="BoundingBox.Unset"/> if not bounding box could be found</returns> public static BoundingBox GetBoundingBox(this Box value, Transform xform) { if (!value.IsValid) { return(BoundingBox.Unset); } // BoundingBox constructor already checks for Identity xform //if (xform.IsIdentity) // return value.BoundingBox; return(new BoundingBox(value.GetCorners(), xform)); }
/// <summary> /// Ensure the line extends all the way through a box. /// Note, this does not result in the shortest possible line that overlaps the box. /// </summary> /// <param name="box">Box to extend through.</param> /// <param name="additionalLength">Additional length to append at both sides of the line.</param> /// <returns>true on success, false on failure.</returns> /// <since>5.0</since> public bool ExtendThroughBox(Box box, double additionalLength) { if (!IsValid) { return(false); } if (!box.IsValid) { return(false); } return(ExtendThroughPointSet(box.GetCorners(), additionalLength)); }
/// <summary> /// Ensure the line extends all the way through a box. /// Note, this does not result in the shortest possible line that overlaps the box. /// </summary> /// <param name="box">Box to extend through.</param> /// <returns>true on success, false on failure.</returns> /// <since>5.0</since> public bool ExtendThroughBox(Box box) { if (!IsValid) { return(false); } if (!box.IsValid) { return(false); } return(ExtendThroughPointSet(box.GetCorners(), 0.0)); }
/// <summary> /// Extend this plane through a Box. /// </summary> /// <param name="box">A box to use for extension.</param> /// <param name="s"> /// If this function returns true, /// the s parameter returns the Interval on the plane along the X direction that will /// encompass the Box. /// </param> /// <param name="t"> /// If this function returns true, /// the t parameter returns the Interval on the plane along the Y direction that will /// encompass the Box. /// </param> /// <returns>true on success, false on failure.</returns> /// <since>5.0</since> public bool ExtendThroughBox(Box box, out Interval s, out Interval t) { s = Interval.Unset; t = Interval.Unset; if (!IsValid) { return(false); } if (!box.IsValid) { return(false); } return(ExtendThroughPoints(box.GetCorners(), ref s, ref t)); }
//HATCH FILL REGION - infills a planar region with a hatching pattern public void Filler(List<double> infDens, List<double> infRot) { double tolerance = 0.001; //double overlaptol = 0.0; double crossSecHyp = Math.Sqrt(Math.Pow(crossSec, 2) * 2); curveInfill = new List<Curve>[planarBreps.Count]; //Create List of Infill Curves for each Planar Region for (int u = 0; u < planarBreps.Count; u++) { //Rotate Plane for Filling double rotationRad = infRot[u] * 0.0174532925; Plane plane = Plane.WorldXY; plane.Rotate(rotationRad, Plane.WorldXY.ZAxis); //Create Bounding Box Box bbox = new Box(); planarBreps[u].GetBoundingBox(plane, out bbox); //Get Corners Point3d[] cornerPts = bbox.GetCorners(); //Draw Parallel Lines LineCurve baseLine = new LineCurve(cornerPts[0], cornerPts[1]); LineCurve baseLine2 = new LineCurve(cornerPts[3], cornerPts[2]); //int nPts = (int)Math.Round((baseLine.Line.Length/crossSec),0); Point3d[] basePts = new Point3d[0]; Point3d[] basePts2 = new Point3d[0]; double length = baseLine.Line.Length; double floatdivisions = length / crossSec; double density = infDens[u]; int divisions = (int)Math.Round((floatdivisions * density)); //Divide Lines by Fill Density ratio baseLine.DivideByCount(divisions, true, out basePts); baseLine2.DivideByCount(divisions, true, out basePts2); if (divisions == 0) { curveInfill[u] = new List<Curve>(); return; } Curve[][] intCurve = new Curve[basePts.Length][]; List<Curve> intCurves = new List<Curve>(); for (int i = 0; i < basePts.Length; i++) { LineCurve intLine = new LineCurve(basePts[i], basePts2[i]); Point3d[] intPts = new Point3d[0]; BrepFace r_Infill = planarBreps[u].Faces[0]; Curve[] int_Curve = new Curve[0]; //Intersect Curves with Regions Intersection.CurveBrepFace(intLine, r_Infill, tolerance, out int_Curve, out intPts); intCurve[i] = int_Curve; //Convert resulting Curves into LineCurves for (int j = 0; j < int_Curve.Length; j++) { LineCurve line = new LineCurve(int_Curve[j].PointAtStart, int_Curve[j].PointAtEnd); intCurve[i][j] = line; //intCurves[j].Add(int_Curve[j]); intCurves.Add(line); } } //Rotate Array List<Curve>[] int_Curves = RotatetoListArray(intCurve); List<Curve> joinLines = new List<Curve>(); List<Curve> p_lines = new List<Curve>(); for (int l = 0; l < int_Curves.Length; l++) { for (int k = 1; k < int_Curves[l].Count; k += 2) { int_Curves[l][k].Reverse(); } } //Create a list of points for all connected lines in the infill. Do this for each seperate string of segments for (int l = 0; l < int_Curves.Length; l++) { List<Point3d> plinePts = new List<Point3d>(); if (int_Curves[l].Count > 0) { plinePts.Add(int_Curves[l][0].PointAtStart); for (int k = 1; k < int_Curves[l].Count; k++) { plinePts.Add(int_Curves[l][k - 1].PointAtEnd); plinePts.Add(int_Curves[l][k].PointAtStart); plinePts.Add(int_Curves[l][k].PointAtEnd); } PolylineCurve plCurve = new PolylineCurve(plinePts); Curve curve = plCurve.ToNurbsCurve(); p_lines.Add(curve); } } List<Curve> curve_s = p_lines; curveInfill[u] = p_lines; } }
/// <summary> /// Draws the edges of a Box object. /// </summary> /// <param name="box">Box to draw.</param> /// <param name="color">Color to draw in.</param> /// <param name="thickness">Thickness (in pixels) of box edges.</param> public void DrawBox(Box box, System.Drawing.Color color, int thickness) { if (!box.IsValid) { return; } bool dx = box.X.IsSingleton; bool dy = box.Y.IsSingleton; bool dz = box.Z.IsSingleton; // If degenerate in all directions, then there's nothing to draw. if (dx && dy && dz) { return; } Point3d[] C = box.GetCorners(); // If degenerate in two directions, we can draw a single line. if (dx && dy) { DrawLine(C[0], C[4], color, thickness); return; } if (dx && dz) { DrawLine(C[0], C[3], color, thickness); return; } if (dy && dz) { DrawLine(C[0], C[1], color, thickness); return; } // If degenerate in one direction, we can draw rectangles. if (dx) { DrawLine(C[0], C[3], color, thickness); DrawLine(C[3], C[7], color, thickness); DrawLine(C[7], C[4], color, thickness); DrawLine(C[4], C[0], color, thickness); return; } if (dy) { DrawLine(C[0], C[1], color, thickness); DrawLine(C[1], C[5], color, thickness); DrawLine(C[5], C[4], color, thickness); DrawLine(C[4], C[0], color, thickness); return; } if (dz) { DrawLine(C[0], C[1], color, thickness); DrawLine(C[1], C[2], color, thickness); DrawLine(C[2], C[3], color, thickness); DrawLine(C[3], C[0], color, thickness); return; } // Draw all 12 edges DrawLine(C[0], C[1], color, thickness); DrawLine(C[1], C[2], color, thickness); DrawLine(C[2], C[3], color, thickness); DrawLine(C[3], C[0], color, thickness); DrawLine(C[0], C[4], color, thickness); DrawLine(C[1], C[5], color, thickness); DrawLine(C[2], C[6], color, thickness); DrawLine(C[3], C[7], color, thickness); DrawLine(C[4], C[5], color, thickness); DrawLine(C[5], C[6], color, thickness); DrawLine(C[6], C[7], color, thickness); DrawLine(C[7], C[4], color, thickness); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { // 1. Retrieve and validate data var cell = new UnitCell(); GeometryBase designSpace = null; Plane orientationPlane = Plane.Unset; double xCellSize = 0; double yCellSize = 0; double zCellSize = 0; double minLength = 0; // the trim tolerance (i.e. minimum strut length) double maxLength = 0; bool strictlyIn = false; if (!DA.GetData(0, ref cell)) { return; } if (!DA.GetData(1, ref designSpace)) { return; } if (!DA.GetData(2, ref orientationPlane)) { return; } if (!DA.GetData(3, ref xCellSize)) { return; } if (!DA.GetData(4, ref yCellSize)) { return; } if (!DA.GetData(5, ref zCellSize)) { return; } if (!DA.GetData(6, ref minLength)) { return; } if (!DA.GetData(7, ref maxLength)) { return; } if (!DA.GetData(8, ref strictlyIn)) { return; } if (!cell.isValid) { return; } if (!designSpace.IsValid) { return; } if (!orientationPlane.IsValid) { return; } if (xCellSize == 0) { return; } if (yCellSize == 0) { return; } if (zCellSize == 0) { return; } if (minLength>=xCellSize || minLength>=yCellSize || minLength>=zCellSize) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Tolerance parameter cannot be larger than the unit cell dimensions."); return; } // 2. Validate the design space int spaceType = FrameTools.ValidateSpace(ref designSpace); if (spaceType == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Design space must be a closed Brep, Mesh or Surface"); return; } double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance; // 3. Compute oriented bounding box and its corner points Box bBox = new Box(); designSpace.GetBoundingBox(orientationPlane, out bBox); Point3d[] bBoxCorners = bBox.GetCorners(); // Set basePlane based on the bounding box Plane basePlane = new Plane(bBoxCorners[0], bBoxCorners[1], bBoxCorners[3]); // 4. Determine number of iterations required to fill the box, and package into array double xLength = bBoxCorners[0].DistanceTo(bBoxCorners[1]); double yLength = bBoxCorners[0].DistanceTo(bBoxCorners[3]); double zLength = bBoxCorners[0].DistanceTo(bBoxCorners[4]); int nX = (int)Math.Ceiling(xLength / xCellSize); // Roundup to next integer if non-integer int nY = (int)Math.Ceiling(yLength / yCellSize); int nZ = (int)Math.Ceiling(zLength / zCellSize); float[] N = new float[3] { nX, nY, nZ }; // 5. Initialize nodeTree var lattice = new Lattice(); // 6. Prepare cell (this is a UnitCell object) cell = cell.Duplicate(); cell.FormatTopology(); // 7. Define iteration vectors in each direction (accounting for Cell Size) Vector3d vectorU = xCellSize * basePlane.XAxis; Vector3d vectorV = yCellSize * basePlane.YAxis; Vector3d vectorW = zCellSize * basePlane.ZAxis; // 8. Map nodes to design space // Loop through the uvw cell grid for (int u = 0; u <= N[0]; u++) { for (int v = 0; v <= N[1]; v++) { for (int w = 0; w <= N[2]; w++) { // Construct cell path in tree GH_Path treePath = new GH_Path(u, v, w); // Fetch the list of nodes to append to, or initialise it var nodeList = lattice.Nodes.EnsurePath(treePath); // This loop maps each node in the cell for (int i = 0; i < cell.Nodes.Count; i++) { double usub = cell.Nodes[i].X; // u-position within unit cell (local) double vsub = cell.Nodes[i].Y; // v-position within unit cell (local) double wsub = cell.Nodes[i].Z; // w-position within unit cell (local) double[] uvw = { u + usub, v + vsub, w + wsub }; // uvw-position (global) // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell) bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0); // Check if current uvw-position is beyond the upper boundary bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]); if (isOutsideCell || isOutsideSpace) { nodeList.Add(null); } else { // Compute position vector Vector3d V = uvw[0] * vectorU + uvw[1] * vectorV + uvw[2] * vectorW; var newNode = new LatticeNode(basePlane.Origin + V); // Check if point is inside - use unstrict tolerance, meaning it can be outside the surface by the specified tolerance bool isInside = FrameTools.IsPointInside(designSpace, newNode.Point3d, spaceType, tol, strictlyIn); // Set the node state (it's location wrt the design space) if (isInside) { newNode.State = LatticeNodeState.Inside; } else { newNode.State = LatticeNodeState.Outside; } // Add node to tree nodeList.Add(newNode); } } } } } // 9. Map struts to the node tree lattice.UniformMapping(cell, designSpace, spaceType, N, minLength, maxLength); // 10. Set output DA.SetDataList(0, lattice.Struts); }
/// <summary> /// Test a box for Box inclusion. /// </summary> /// <param name="box">Box to test.</param> /// <param name="strict">If true, the box needs to be fully on the inside of this Box. /// I.e. coincident boxes will be considered 'outside'.</param> /// <returns>true if the box is (strictly) on the inside of this Box.</returns> public bool Contains(Box box, bool strict) { if (!box.IsValid) { return false; } Point3d[] c = box.GetCorners(); for (int i = 0; i < c.Length; i++) { if (!Contains(c[i], strict)) { return false; } } return true; }