예제 #1
0
        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));
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        /// <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));
        }
예제 #5
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));
        }
예제 #6
0
        //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);
    }
예제 #8
0
        /// <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);
        }
예제 #9
0
    /// <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;
    }