Пример #1
0
 public PlanarMesher(List <String> tErrorContainer, WingedMesh tWingMesh, Mesh tRhinoMesh, int tNumPanels, int metric, GH_PreviewUtil tPreview)
 {
     errorContainer   = tErrorContainer;
     wingMesh         = tWingMesh;
     rhinoMesh        = tRhinoMesh;
     numPanels        = tNumPanels;
     currentPartition = new Partition(wingMesh.faces.Count, this);
     preview          = tPreview;
     metricRef        = metric;
 }
Пример #2
0
 public PlanarMesher(List<String> tErrorContainer, WingedMesh tWingMesh, Mesh tRhinoMesh, int tNumPanels, int metric, GH_PreviewUtil tPreview)
 {
     errorContainer = tErrorContainer;
     wingMesh = tWingMesh;
     rhinoMesh = tRhinoMesh;
     numPanels = tNumPanels;
     currentPartition = new Partition(wingMesh.faces.Count, this);
     preview = tPreview;
     metricRef = metric;
 }
Пример #3
0
 internal void drawProxies(GH_PreviewUtil preview)
 {
     for (int i = 0; i < proxies.Count; i++)
     {
         preview.AddMesh(proxies[i].proxyAsMesh);
         preview.WireColour = UsefulFunctions.returnRandomColour(i);
         preview.Redraw();
         preview.Clear();
     }
 }
Пример #4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages passed by controller, partition, etc.
            List<String> errorContainer = new List<String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            Mesh baseMesh = new Rhino.Geometry.Mesh();
            int errorMetricIdentifer = -1;
            int numPanels = -1;

            //Retrieve input data
            if (!DA.GetData(0, ref baseMesh)) { return; }
            if (!DA.GetData(1, ref errorMetricIdentifer)) { return; }
            if (!DA.GetData(2, ref numPanels)) { return; }

            if (baseMesh.DisjointMeshCount > 1)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Problem with mesh input - disjoint mesh");
            }
            else
            {
                //compute and unify normal
                baseMesh.Normals.ComputeNormals();
                baseMesh.UnifyNormals();

                //create wingedmesh from rhinomesh
                WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);

                PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, baseMesh, numPanels, errorMetricIdentifer, preview);

                controller.createFirstCluster();

                for (int i = 0; i < 40; i++)
                {
                    controller.iterateCluster();
                    //controller.currentPartition.drawProxies(preview);
                }

                controller.createConnectivityMesh();

                //creating voronoi
                WingedMesh voronoiMesh = new WingedMesh(errorContainer, controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines());

                //set all the output data
                DA.SetDataList(0, voronoiMesh.convertWingedMeshToPolylines());
            }

            foreach (var item in errorContainer)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, item);
            }
        }
Пример #5
0
 internal void drawProxies(GH_PreviewUtil preview)
 {
     for (int i = 0; i < proxies.Count; i++)
     {
         preview.AddMesh(proxies[i].proxyAsMesh);
         preview.WireColour = UsefulFunctions.returnRandomColour(i);
         preview.Redraw();
         preview.Clear();
     }
 }
Пример #6
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)
        {
            Surface S = null;

            if (!DA.GetData(0, ref S))
            {
                return;
            }

            Point3d P = Point3d.Unset;

            if (!DA.GetData(1, ref P))
            {
                P = S.PointAt(S.Domain(0).Mid, S.Domain(1).Mid);
            }

            double R = Rhino.RhinoMath.UnsetValue;

            if (!DA.GetData(2, ref R))
            {
                return;
            }

            double A = Rhino.RhinoMath.UnsetValue;

            if (!DA.GetData(3, ref A))
            {
                return;
            }

            int max = 0;

            if (!DA.GetData(4, ref max))
            {
                return;
            }

            Boolean extend = false;

            if (!DA.GetData(5, ref extend))
            {
                return;
            }

            if (R <= 0)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh edge length must be a positive, non-zero number.");
                return;
            }

            // Extend surface beyond boundaries to get a better coverage from the net
            if (extend)
            {
                S = S.Extend(IsoStatus.North, R, true);
                S = S.Extend(IsoStatus.East, R, true);
                S = S.Extend(IsoStatus.South, R, true);
                S = S.Extend(IsoStatus.West, R, true);
            }


            // starting point
            double u0, v0;

            S.ClosestPoint(P, out u0, out v0);
            // get two (four) orthogonal directions (in plane of surface at starting point)
            Plane plane = new Plane(S.PointAt(u0, v0), S.NormalAt(u0, v0));

            plane.Rotate(Rhino.RhinoMath.ToRadians(A), S.NormalAt(u0, v0));
            Vector3d[] dir = new Vector3d[] {
                plane.XAxis *  R,
                plane.YAxis *  R,
                plane.XAxis * -R,
                       plane.YAxis * -R
            };


            // for each direction, walk out (and store list of points)
            double u, v;

            List <Point3d>[] axis = new List <Point3d> [4];
            for (int i = 0; i < 4; i++)
            {
                // set u and v to starting point
                u = u0;
                v = v0;
                List <Point3d> pts = new List <Point3d>();
                for (int j = 0; j < max + 1; j++)
                {
                    // get point and normal for uv
                    Point3d  pt = S.PointAt(u, v);
                    Vector3d n  = S.NormalAt(u, v);
                    n *= R;
                    // add point to list
                    pts.Add(pt);
                    // create forward facing arc and find intersection point with surface (as uv)
                    Arc arc = new Arc(pt + n, pt + dir[i], pt - n);
                    CurveIntersections isct =
                        Intersection.CurveSurface(arc.ToNurbsCurve(), S, 0.01, 0.01);
                    if (isct.Count > 0)
                    {
                        isct[0].SurfacePointParameter(out u, out v);
                    }
                    else
                    {
                        break;
                    }
                    // adjust direction vector (new position - old position)
                    dir[i] = S.PointAt(u, v) - pt;
                }
                axis[i] = pts;
            }


            // now that we have the axes, start to build up the mesh quads in between
            GH_PreviewUtil preview = new GH_PreviewUtil(GetValue("Animate", false));

            Rhino.Geometry.Mesh mesh = new Rhino.Geometry.Mesh(); // target mesh
            for (int k = 0; k < 4; k++)
            {
                int k0      = (k + 1) % 4;
                int padding = 10;
                Rhino.Geometry.Mesh qmesh = new Rhino.Geometry.Mesh();                            // local mesh for quadrant
                Point3d[,] quad = new Point3d[axis[k].Count + padding, axis[k0].Count + padding]; // 2d array of points
                int[,] qindex   = new int[axis[k].Count + padding, axis[k0].Count + padding];     // 2d array of points' indices in local mesh
                int count = 0;
                for (int i = 0; i < axis[k0].Count; i++)
                {
                    // add axis vertex to mesh and store point and index in corresponding 2d arrays
                    quad[0, i] = axis[k0][i];
                    qmesh.Vertices.Add(axis[k0][i]);
                    qindex[0, i] = count++;
                }

                for (int i = 1; i < quad.GetLength(0); i++)
                {
                    if (i < axis[k].Count)
                    {
                        // add axis vertex
                        quad[i, 0] = axis[k][i];
                        qmesh.Vertices.Add(axis[k][i]);
                        qindex[i, 0] = count++;
                    }
                    // for each column attempt to locate a new vertex in the grid
                    for (int j = 1; j < quad.GetLength(1); j++)
                    {
                        // if quad[i - 1, j] doesn't exist, try to add it and continue (or else break the current row)
                        if (quad[i - 1, j] == new Point3d())
                        {
                            if (j < 2)
                            {
                                break;
                            }
                            CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j - 1], quad[i - 1, j - 2], R);
                            if (isct.Count > 0)
                            {
                                quad[i - 1, j] = isct[0].PointB;
                                qmesh.Vertices.Add(quad[i - 1, j]);
                                qindex[i - 1, j] = count++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        // if quad[i, j - 1] doesn't exist, try to create quad[i, j] by projection and skip mesh face creation
                        if (quad[i, j - 1] == new Point3d())
                        {
                            if (i < 2)
                            {
                                break;
                            }
                            CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j], quad[i - 2, j], R);
                            if (isct.Count > 0)
                            {
                                quad[i, j] = isct[0].PointB;
                                qmesh.Vertices.Add(quad[i, j]);
                                qindex[i, j] = count++;
                                continue;
                            }
                        }
                        // construct a sphere at each neighbouring vertex ([i,j-1] and [i-1,j]) and intersect
                        Sphere sph1 = new Sphere(quad[i, j - 1], R);
                        Sphere sph2 = new Sphere(quad[i - 1, j], R);
                        Circle cir;
                        if (Intersection.SphereSphere(sph1, sph2, out cir) == SphereSphereIntersection.Circle)
                        {
                            // intersect circle with surface
                            CurveIntersections cin =
                                Intersection.CurveSurface(NurbsCurve.CreateFromCircle(cir), S, 0.01, 0.01);
                            // attempt to find the new vertex (i.e not [i-1,j-1])
                            foreach (IntersectionEvent ie in cin)
                            {
                                if ((ie.PointA - quad[i - 1, j - 1]).Length > 0.2 * R) // compare with a tolerance, rather than exact comparison
                                {
                                    quad[i, j] = ie.PointA;
                                    qmesh.Vertices.Add(quad[i, j]);
                                    qindex[i, j] = count++;
                                    // create quad-face
                                    qmesh.Faces.AddFace(qindex[i, j], qindex[i - 1, j], qindex[i - 1, j - 1], qindex[i, j - 1]);
                                    break;
                                }
                            }
                            if (preview.Enabled)
                            {
                                preview.Clear();
                                preview.AddMesh(mesh);
                                preview.AddMesh(qmesh);
                                preview.Redraw();
                            }
                        }
                    }
                }
                // add local mesh to target
                mesh.Append(qmesh);
            }

            // weld mesh to remove duplicate vertices along axes
            mesh.Weld(Math.PI);
            mesh.Compact();
            mesh.Normals.ComputeNormals();


            DA.SetData(0, mesh);

            preview.Clear();
        }
Пример #7
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages
            List<String> errorContainer = new List<String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            Mesh baseMesh = new Rhino.Geometry.Mesh();
            int errorMetricIdentifer = -1;
            int numPanels = -1;
            Boolean run = false;

            //Retrieve input data
            if (!DA.GetData(0, ref baseMesh)) { return; }
            if (!DA.GetData(1, ref errorMetricIdentifer)) { return; }
            if (!DA.GetData(2, ref numPanels)) { return; }
            if (!DA.GetData(3, ref run)) { return; }

            if (run)
            {

                if (baseMesh.DisjointMeshCount > 1)
                {
                    errorContainer.Add("Problem with mesh input - disjoint mesh");
                }
                else
                {
                    //compute and unify normal
                    baseMesh.Normals.ComputeNormals();
                    baseMesh.UnifyNormals();

                    //create wingedmesh from rhinomesh
                    WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);

                    PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, baseMesh, numPanels, errorMetricIdentifer, preview);

                    controller.createFirstCluster();

                    for (int i = 0; i < 40; i++)
                    {
                        controller.iterateCluster();
                        controller.currentPartition.drawProxies(preview);
                    }

                    controller.createConnectivityMesh();

                    //creating voronoi
                    WingedMesh voronoiMesh = new WingedMesh(errorContainer, controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines());

                    controller.planariseConnectivityMesh();

                    //convert faces edges to polylines for viewing
                    List<Polyline> boundaryEdges = controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines();

                    List<Plane> proxyPlanes = new List<Plane>();
                    foreach (Proxy proxy in controller.currentPartition.proxies)
                    {
                        proxyPlanes.Add(proxy.rhinoPlane);
                    }
                    List<Mesh> proxyMeshes = new List<Mesh>();
                    foreach (Proxy proxy in controller.currentPartition.proxies)
                    {
                        proxyMeshes.Add(proxy.proxyAsMesh);
                    }

                    List<Vector3d> faceNormals = new List<Vector3d>();
                    List<Point3d> faceCentres = new List<Point3d>();
                    for (int i = 0; i < controller.currentPartition.proxyToMesh.faces.Count; i++)
                    {
                        faceNormals.Add(new Vector3d(controller.currentPartition.proxyToMesh.faces[i].faceNormal));
                        faceCentres.Add(new Point3d(controller.currentPartition.proxyToMesh.faces[i].faceCentre));
                    }

                    //set all the output data
                    DA.SetDataList(1, proxyPlanes);
                    DA.SetDataList(2, boundaryEdges);
                    DA.SetData(3, controller.currentPartition.proxyToMesh);
                    DA.SetDataList(4, faceNormals);
                    DA.SetDataList(5, faceCentres);
                    DA.SetDataList(6, voronoiMesh.convertWingedMeshToPolylines());
                }
                DA.SetDataList(0, errorContainer);
            }
        }
Пример #8
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages passed by controller, partition, etc.
            List<String> errorContainer = new List<String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            List<Curve> baseCurves = new List<Curve>();

            //Retrieve input data
            if (!DA.GetDataList(0, baseCurves))
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Couldn't infer list of polyline face boundaries from input");
                return;
            }
            //if (!DA.GetData(1, ref run)) { return; }

            List<Polyline> baseMesh = new List<Polyline>();
            for (int i = 0; i < baseCurves.Count; i++)
	        {
                 Polyline pl;
		         if (baseCurves[i].TryGetPolyline(out pl))
                 {
                     baseMesh.Add(pl);
                 }
                 else
                 {
                     this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Couldn't get a polyline from boundary curve #" + i.ToString());
                 }
	        }

            try // catch any unexpected errors
            {
                // TODO: disjoint mesh check

                //create wingedmesh from rhinomesh
                WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);
                myMesh.calculateNormals();

                PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, null, myMesh.faces.Count, -1, preview);

                controller.CreateFromInputMesh();
                controller.createConnectivityMesh();
                controller.planariseConnectivityMesh();

                //convert faces edges to polylines for viewing
                List<Polyline> boundaryEdges = controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines();

                List<Plane> proxyPlanes = new List<Plane>();
                foreach (Proxy proxy in controller.currentPartition.proxies)
                {
                    proxyPlanes.Add(proxy.rhinoPlane);
                }
                List<Mesh> proxyMeshes = new List<Mesh>();
                foreach (Proxy proxy in controller.currentPartition.proxies)
                {
                    proxyMeshes.Add(proxy.proxyAsMesh);
                }

                //set all the output data
                DA.SetDataList(0, proxyPlanes);
                DA.SetDataList(1, boundaryEdges);
            }
            catch (Exception e)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.StackTrace);
            }

            foreach (var item in errorContainer)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, item);
            }
        }
Пример #9
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages passed by controller, partition, etc.
            List <String> errorContainer = new List <String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            List <Curve> baseCurves = new List <Curve>();

            //Retrieve input data
            if (!DA.GetDataList(0, baseCurves))
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Couldn't infer list of polyline face boundaries from input");
                return;
            }
            //if (!DA.GetData(1, ref run)) { return; }

            List <Polyline> baseMesh = new List <Polyline>();

            for (int i = 0; i < baseCurves.Count; i++)
            {
                Polyline pl;
                if (baseCurves[i].TryGetPolyline(out pl))
                {
                    baseMesh.Add(pl);
                }
                else
                {
                    this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Couldn't get a polyline from boundary curve #" + i.ToString());
                }
            }

            try // catch any unexpected errors
            {
                // TODO: disjoint mesh check

                //create wingedmesh from rhinomesh
                WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);
                myMesh.calculateNormals();

                PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, null, myMesh.faces.Count, -1, preview);

                controller.CreateFromInputMesh();
                controller.createConnectivityMesh();
                controller.planariseConnectivityMesh();

                //convert faces edges to polylines for viewing
                List <Polyline> boundaryEdges = controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines();

                List <Plane> proxyPlanes = new List <Plane>();
                foreach (Proxy proxy in controller.currentPartition.proxies)
                {
                    proxyPlanes.Add(proxy.rhinoPlane);
                }
                List <Mesh> proxyMeshes = new List <Mesh>();
                foreach (Proxy proxy in controller.currentPartition.proxies)
                {
                    proxyMeshes.Add(proxy.proxyAsMesh);
                }

                //set all the output data
                DA.SetDataList(0, proxyPlanes);
                DA.SetDataList(1, boundaryEdges);
            }
            catch (Exception e)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.StackTrace);
            }

            foreach (var item in errorContainer)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, item);
            }
        }
Пример #10
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages passed by controller, partition, etc.
            List <String> errorContainer = new List <String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            Mesh baseMesh             = new Rhino.Geometry.Mesh();
            int  errorMetricIdentifer = -1;
            int  numPanels            = -1;

            //Retrieve input data
            if (!DA.GetData(0, ref baseMesh))
            {
                return;
            }
            if (!DA.GetData(1, ref errorMetricIdentifer))
            {
                return;
            }
            if (!DA.GetData(2, ref numPanels))
            {
                return;
            }

            if (baseMesh.DisjointMeshCount > 1)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Problem with mesh input - disjoint mesh");
            }
            else
            {
                //compute and unify normal
                baseMesh.Normals.ComputeNormals();
                baseMesh.UnifyNormals();

                //create wingedmesh from rhinomesh
                WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);

                PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, baseMesh, numPanels, errorMetricIdentifer, preview);

                controller.createFirstCluster();

                for (int i = 0; i < 40; i++)
                {
                    controller.iterateCluster();
                    //controller.currentPartition.drawProxies(preview);
                }

                controller.createConnectivityMesh();

                //creating voronoi
                WingedMesh voronoiMesh = new WingedMesh(errorContainer, controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines());

                //set all the output data
                DA.SetDataList(0, voronoiMesh.convertWingedMeshToPolylines());
            }

            foreach (var item in errorContainer)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, item);
            }
        }
Пример #11
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //container for errors/messages
            List <String> errorContainer = new List <String>();

            GH_PreviewUtil preview = new GH_PreviewUtil(true);

            //declare placeholder variables and assign initial empty mesh
            Mesh    baseMesh             = new Rhino.Geometry.Mesh();
            int     errorMetricIdentifer = -1;
            int     numPanels            = -1;
            Boolean run = false;

            //Retrieve input data
            if (!DA.GetData(0, ref baseMesh))
            {
                return;
            }
            if (!DA.GetData(1, ref errorMetricIdentifer))
            {
                return;
            }
            if (!DA.GetData(2, ref numPanels))
            {
                return;
            }
            if (!DA.GetData(3, ref run))
            {
                return;
            }

            if (run)
            {
                if (baseMesh.DisjointMeshCount > 1)
                {
                    errorContainer.Add("Problem with mesh input - disjoint mesh");
                }
                else
                {
                    //compute and unify normal
                    baseMesh.Normals.ComputeNormals();
                    baseMesh.UnifyNormals();

                    //create wingedmesh from rhinomesh
                    WingedMesh myMesh = new WingedMesh(errorContainer, baseMesh);

                    PlanarMesher controller = new PlanarMesher(errorContainer, myMesh, baseMesh, numPanels, errorMetricIdentifer, preview);

                    controller.createFirstCluster();

                    for (int i = 0; i < 40; i++)
                    {
                        controller.iterateCluster();
                        controller.currentPartition.drawProxies(preview);
                    }

                    controller.createConnectivityMesh();

                    //creating voronoi
                    WingedMesh voronoiMesh = new WingedMesh(errorContainer, controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines());

                    controller.planariseConnectivityMesh();

                    //convert faces edges to polylines for viewing
                    List <Polyline> boundaryEdges = controller.currentPartition.proxyToMesh.convertWingedMeshToPolylines();

                    List <Plane> proxyPlanes = new List <Plane>();
                    foreach (Proxy proxy in controller.currentPartition.proxies)
                    {
                        proxyPlanes.Add(proxy.rhinoPlane);
                    }
                    List <Mesh> proxyMeshes = new List <Mesh>();
                    foreach (Proxy proxy in controller.currentPartition.proxies)
                    {
                        proxyMeshes.Add(proxy.proxyAsMesh);
                    }

                    List <Vector3d> faceNormals = new List <Vector3d>();
                    List <Point3d>  faceCentres = new List <Point3d>();
                    for (int i = 0; i < controller.currentPartition.proxyToMesh.faces.Count; i++)
                    {
                        faceNormals.Add(new Vector3d(controller.currentPartition.proxyToMesh.faces[i].faceNormal));
                        faceCentres.Add(new Point3d(controller.currentPartition.proxyToMesh.faces[i].faceCentre));
                    }

                    //set all the output data
                    DA.SetDataList(1, proxyPlanes);
                    DA.SetDataList(2, boundaryEdges);
                    DA.SetData(3, controller.currentPartition.proxyToMesh);
                    DA.SetDataList(4, faceNormals);
                    DA.SetDataList(5, faceCentres);
                    DA.SetDataList(6, voronoiMesh.convertWingedMeshToPolylines());
                }
                DA.SetDataList(0, errorContainer);
            }
        }
Пример #12
0
            protected override void SolveInstance(IGH_DataAccess DA)
            {
                //Input
                Surface S = null;

                if (!DA.GetData(0, ref S))
                {
                    return;
                }

                Point3d P = Point3d.Unset;

                if (!DA.GetData(1, ref P))
                {
                    P = S.PointAt(S.Domain(0).Mid, S.Domain(1).Mid);
                }

                double R = Rhino.RhinoMath.UnsetValue;

                if (!DA.GetData(2, ref R))
                {
                    return;
                }

                double A = Rhino.RhinoMath.UnsetValue;

                if (!DA.GetData(3, ref A))
                {
                    return;
                }

                int max = 0;

                if (!DA.GetData(4, ref max))
                {
                    return;
                }

                Boolean extend = false;

                if (!DA.GetData(5, ref extend))
                {
                    return;
                }

                if (R <= 0)
                {
                    this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh edge length must be a positive, non-zero number.");
                    return;
                }

                Surface Sold = S;

                if (extend)   //Extend more and trim edges?
                {
                    S = S.Extend(IsoStatus.North, R * 2, true);
                    S = S.Extend(IsoStatus.East, R * 2, true);
                    S = S.Extend(IsoStatus.South, R * 2, true);
                    S = S.Extend(IsoStatus.West, R * 2, true);
                }

                //----------------------------------------------------------------------------------------------------------//
                //Solution

                // starting point
                double u0, v0;

                S.ClosestPoint(P, out u0, out v0);

                //Create plane on surface by point and surface normal, plane x,y axis are directions for the net
                Plane plane = new Plane(S.PointAt(u0, v0), S.NormalAt(u0, v0));

                plane.Rotate(Rhino.RhinoMath.ToRadians(A), S.NormalAt(u0, v0));
                Vector3d[] dir = new Vector3d[] { plane.XAxis *R, plane.YAxis *R, plane.XAxis * -R, plane.YAxis * -R };

                //Surface
                Curve[] MyNakedEdges = Sold.ToBrep().DuplicateNakedEdgeCurves(true, false);
                Mesh[]  meshes       = new Mesh[] { new Mesh(), new Mesh(), new Mesh(), new Mesh() };

                //----------------------------------------------------------------------------------------------------------//
                //Create axis
                // for each direction, walk out (and store list of points)

                double u, v;

                List <Point3d>[] axis = new List <Point3d> [4];
                List <Arc>[]     arcs = new List <Arc> [4];
                polylines = new List <Polyline>();

                for (int i = 0; i < 4; i++)
                {
                    // set u and v to starting point
                    u = u0;
                    v = v0;
                    List <Point3d> pts        = new List <Point3d>();
                    List <Arc>     arcCurrent = new List <Arc>();


                    for (int j = 0; j < max + 1; j++)
                    {
                        Point3d pt = S.PointAt(u, v); // get point and normal for uv
                        pts.Add(pt);

                        Vector3d srfNormal = S.NormalAt(u, v) * R;

                        Arc arc = new Arc(pt + srfNormal, pt + dir[i], pt - srfNormal); // create forward facing arc and find intersection point with surface (as uv)
                        arcCurrent.Add(arc);
                        CurveIntersections isct = Intersection.CurveSurface(arc.ToNurbsCurve(), S, 0.01, 0.01);


                        if (isct.Count > 0)
                        {
                            isct[0].SurfacePointParameter(out u, out v);
                        }
                        else
                        {
                            break;
                        }

                        // adjust direction vector (new position - old position)
                        dir[i] = S.PointAt(u, v) - pt;
                    }

                    axis[i] = pts;
                    arcs[i] = arcCurrent;
                }



                //----------------------------------------------------------------------------------------------------------//
                //Build up the mesh quads in between

                GH_PreviewUtil preview = new GH_PreviewUtil(GetValue("Animate", false));

                Mesh mesh = new Mesh();     // target mesh

                for (int k = 0; k < 4; k++) //Loop through each axis

                {
                    Mesh qmesh = new Mesh();                                                // local mesh for quadrant

                    int k0 = (k + 1) % 4;                                                   //Take neighbour id
                    Point3d[,] quad = new Point3d[axis[k].Count + 10, axis[k0].Count + 10]; // 2d array of points
                    int[,] qindex   = new int[axis[k].Count + 10, axis[k0].Count + 10];     // 2d array of points' indices in local mesh

                    int count = 0;

                    for (int i = 0; i < axis[k0].Count; i++)
                    {
                        quad[0, i] = axis[k0][i];        //store 2nd axis points in point array
                        qmesh.Vertices.Add(axis[k0][i]); //also add 2nd axis points to mesh
                        qindex[0, i] = count++;          //store indicies
                    }


                    for (int i = 1; i < quad.GetLength(0); i++)
                    {
                        if (i < axis[k].Count)              // add axis vertex
                        {
                            quad[i, 0] = axis[k][i];        //store 1st axis points in point array
                            qmesh.Vertices.Add(axis[k][i]); //also add 1st axis points to mesh
                            qindex[i, 0] = count++;         //store indicies
                        }

                        // for each column attempt to locate a new vertex in the grid
                        for (int j = 1; j < quad.GetLength(1); j++)
                        {
                            // if quad[i - 1, j] doesn't exist, try to add it and continue (or else break the current row)
                            if (quad[i - 1, j] == new Point3d())
                            {
                                if (j < 2)
                                {
                                    break;
                                }

                                CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j - 1], quad[i - 1, j - 2], R);

                                if (isct.Count > 0)
                                {
                                    quad[i - 1, j] = isct[0].PointB;
                                    qmesh.Vertices.Add(quad[i - 1, j]);

                                    qindex[i - 1, j] = count++;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            // if quad[i, j - 1] doesn't exist, try to create quad[i, j] by projection and skip mesh face creation
                            if (quad[i, j - 1] == new Point3d())
                            {
                                if (i < 2)
                                {
                                    break;
                                }

                                CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j], quad[i - 2, j], R);

                                if (isct.Count > 0)
                                {
                                    quad[i, j] = isct[0].PointB;
                                    qmesh.Vertices.Add(quad[i, j]);
                                    qindex[i, j] = count++;

                                    continue;
                                }
                            }

                            // construct a sphere at each neighbouring vertex ([i,j-1] and [i-1,j]) and intersect

                            Sphere sph1 = new Sphere(quad[i, j - 1], R);
                            Sphere sph2 = new Sphere(quad[i - 1, j], R);
                            Circle cir;

                            if (Intersection.SphereSphere(sph1, sph2, out cir) == SphereSphereIntersection.Circle)
                            {
                                CurveIntersections cin = Intersection.CurveSurface(NurbsCurve.CreateFromCircle(cir), S, 0.01, 0.01);// intersect circle with surface

                                // attempt to find the new vertex (i.e not [i-1,j-1])

                                foreach (IntersectionEvent ie in cin)
                                {
                                    if ((ie.PointA - quad[i - 1, j - 1]).Length > 0.2 * R)  // compare with a tolerance, rather than exact comparison

                                    {
                                        quad[i, j] = ie.PointA;
                                        qmesh.Vertices.Add(quad[i, j]);
                                        qindex[i, j] = count++;

                                        Point3d[] facePt = new Point3d[] { quad[i, j], quad[i - 1, j], quad[i - 1, j - 1], quad[i, j - 1] };

                                        Sold.ClosestPoint(quad[i, j], out double u1, out double v1);
                                        Sold.ClosestPoint(quad[i - 1, j], out double u2, out double v2);
                                        Sold.ClosestPoint(quad[i - 1, j - 1], out double u3, out double v3);
                                        Sold.ClosestPoint(quad[i, j - 1], out double u4, out double v4);

                                        double tolerance = 0.01;
                                        bool[] flag      = new bool[] {
                                            Sold.PointAt(u1, v1).DistanceTo(quad[i, j]) < tolerance,
                                            Sold.PointAt(u2, v2).DistanceTo(quad[i - 1, j]) < tolerance,
                                            Sold.PointAt(u3, v3).DistanceTo(quad[i - 1, j - 1]) < tolerance,
                                            Sold.PointAt(u4, v4).DistanceTo(quad[i, j - 1]) < tolerance
                                        };



                                        if (flag[0] && flag[1] && flag[2] && flag[3])
                                        {
                                            qmesh.Faces.AddFace(qindex[i, j], qindex[i - 1, j], qindex[i - 1, j - 1], qindex[i, j - 1]);// create quad-face
                                        }
                                        else if (flag[0] || flag[1] || flag[2] || flag[3])
                                        {
                                            Polyline temp = new Polyline();

                                            for (int p = 0; p < 4; p++)
                                            {
                                                switch (Convert.ToInt32(flag[p]) * 10 + Convert.ToInt32(flag[(p + 1) % 4]))
                                                {
                                                case (11):
                                                    temp.Add(facePt[p]);
                                                    break;

                                                case (10):
                                                    temp.Add(facePt[p]);
                                                    temp.Add(ClosestPointOnNakedEdge(MyNakedEdges, facePt[p], new Line(facePt[p], facePt[(p + 1) % 4])));
                                                    break;

                                                case (1):
                                                    temp.Add(ClosestPointOnNakedEdge(MyNakedEdges, facePt[p], new Line(facePt[p], facePt[(p + 1) % 4])));
                                                    break;

                                                case (0):
                                                    Sold.ClosestPoint(facePt[p], out double u6, out double v6);
                                                    temp.Add(Sold.PointAt(u6, v6));
                                                    break;
                                                }
                                            }
                                            temp.Close();
                                            polylines.Add(temp);



                                            //qmesh.Faces.AddFace(qindex[i, j], qindex[i - 1, j], qindex[i - 1, j - 1], qindex[i, j - 1]);// create quad-face
                                        }



                                        //qmesh.Faces.AddFace(qindex[i, j], qindex[i - 1, j], qindex[i - 1, j - 1], qindex[i, j - 1]);// create quad-face
                                        break;
                                    }
                                }

                                if (preview.Enabled)
                                {
                                    preview.Clear();
                                    preview.AddMesh(mesh);
                                    preview.AddMesh(qmesh);
                                    preview.Redraw();
                                }
                            }
                        }
                    }

                    ;

                    mesh.Append(qmesh);// add local mesh to target
                }

                //----------------------------------------------------------------------------------------------------------//
                //Output
                mesh.Weld(Math.PI);
                mesh.Compact();
                mesh.Normals.ComputeNormals();

                DA.SetData(0, mesh);
                DA.SetDataTree(1, NGonsCore.GrasshopperUtil.IEOfIEToTree(axis, 0));
                DA.SetDataList(2, polylines);

                preview.Clear();
            }
Пример #13
0
            protected override void SolveInstance(IGH_DataAccess DA)
            {
                try {
                    //Input
                    Surface S = s;
                    //if (!DA.GetData(0, ref S)) { return; }
                    DA.GetData(0, ref S);
                    Point3d P = Point3d.Unset;

                    if (!DA.GetData(1, ref P))
                    {
                        P = S.PointAt(S.Domain(0).Mid, S.Domain(1).Mid);
                    }

                    double R = Rhino.RhinoMath.UnsetValue;
                    if (!DA.GetData(2, ref R))
                    {
                        return;
                    }

                    double A = Rhino.RhinoMath.UnsetValue;
                    if (!DA.GetData(3, ref A))
                    {
                        return;
                    }

                    int max = 0;
                    if (!DA.GetData(4, ref max))
                    {
                        return;
                    }

                    Boolean extend = false;
                    if (!DA.GetData(5, ref extend))
                    {
                        return;
                    }

                    if (R <= 0)
                    {
                        this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh edge length must be a positive, non-zero number.");
                        return;
                    }

                    Mesh cutter = new Mesh();
                    //DA.GetData(8, ref cutter);

                    Surface Sold = S;
                    Sold.SetDomain(0, new Interval(0, 1));
                    Sold.SetDomain(1, new Interval(0, 1));
                    PointCloud cornerPoints = new PointCloud(new Point3d[] { Sold.PointAt(0, 0), Sold.PointAt(0, 1), Sold.PointAt(1, 0), Sold.PointAt(1, 1) });


                    if (extend)   //Extend more and trim edges?
                    {
                        S = S.Extend(IsoStatus.North, R * 2, true);
                        S = S.Extend(IsoStatus.East, R * 2, true);
                        S = S.Extend(IsoStatus.South, R * 2, true);
                        S = S.Extend(IsoStatus.West, R * 2, true);
                    }

                    //int L = 0;
                    //int W = 0;
                    //DA.GetData(6, ref L);
                    //DA.GetData(7, ref W);

                    //----------------------------------------------------------------------------------------------------------//
                    //Solution

                    // starting point
                    double u0, v0;
                    S.ClosestPoint(P, out u0, out v0);

                    //Create plane on surface by point and surface normal, plane x,y axis are directions for the net
                    Plane plane = new Plane(S.PointAt(u0, v0), S.NormalAt(u0, v0));
                    plane.Rotate(Rhino.RhinoMath.ToRadians(A), S.NormalAt(u0, v0));
                    Vector3d[] dir = new Vector3d[] { plane.XAxis *R, plane.YAxis *R, plane.XAxis * -R, plane.YAxis * -R };

                    //Surface
                    Curve[] MyNakedEdges     = Sold.ToBrep().DuplicateNakedEdgeCurves(true, false);
                    Curve   SurfaceNakedEdge = Curve.JoinCurves(MyNakedEdges)[0];
                    Mesh[]  meshes           = new Mesh[] { new Mesh(), new Mesh(), new Mesh(), new Mesh() };

                    //----------------------------------------------------------------------------------------------------------//
                    //Create axis
                    // for each direction, walk out (and store list of points)

                    double           u, v;
                    List <Point3d>[] axis = new List <Point3d> [4];
                    List <Arc>[]     arcs = new List <Arc> [4];
                    polylines = new List <Polyline>();

                    for (int i = 0; i < 4; i++)
                    {
                        // set u and v to starting point
                        u = u0;
                        v = v0;
                        List <Point3d> pts        = new List <Point3d>();
                        List <Arc>     arcCurrent = new List <Arc>();


                        for (int j = 0; j < max + 1; j++)
                        {
                            Point3d pt = S.PointAt(u, v); // get point and normal for uv
                            pts.Add(pt);

                            Vector3d srfNormal = S.NormalAt(u, v) * R;

                            Arc arc = new Arc(pt + srfNormal, pt + dir[i], pt - srfNormal); // create forward facing arc and find intersection point with surface (as uv)
                            arcCurrent.Add(arc);
                            CurveIntersections isct = Intersection.CurveSurface(arc.ToNurbsCurve(), S, 0.01, 0.01);


                            if (isct.Count > 0)
                            {
                                isct[0].SurfacePointParameter(out u, out v);
                            }
                            else
                            {
                                break;
                            }

                            // adjust direction vector (new position - old position)
                            dir[i] = S.PointAt(u, v) - pt;
                        }

                        axis[i] = pts;
                        arcs[i] = arcCurrent;
                    }



                    //----------------------------------------------------------------------------------------------------------//
                    //Build up the mesh quads in between
                    Rhino.RhinoApp.ClearCommandHistoryWindow();

                    GH_PreviewUtil preview = new GH_PreviewUtil(GetValue("Animate", false));

                    Mesh         mesh                = new Mesh();                                                                                                                                                   // target mesh
                    Mesh[]       fourMeshes          = new Mesh[4];
                    List <int>[] faceID              = new List <int>[] { new List <int>(), new List <int>(), new List <int>(), new List <int>() };                                                                  //columns lengths
                    List <List <Polyline> >[] strips = new List <List <Polyline> >[] { new List <List <Polyline> >(), new List <List <Polyline> >(), new List <List <Polyline> >(), new List <List <Polyline> >() }; //columns lengths
                    //List<Polyline> cuts = new List<Polyline>();

                    for (int k = 0; k < 4; k++)   //Loop through each axis

                    {
                        Mesh qmesh = new Mesh();                                                         // local mesh for quadrant

                        Point3d[,] quad = new Point3d[axis[k].Count + 10, axis[(k + 1) % 4].Count + 10]; // 2d array of points
                        int[,] qindex   = new int[axis[k].Count + 10, axis[(k + 1) % 4].Count + 10];     // 2d array of points' indices in local mesh

                        int count = 0;

                        //Add 2nd axis particles
                        for (int i = 0; i < axis[(k + 1) % 4].Count; i++)
                        {
                            quad[0, i] = axis[(k + 1) % 4][i];        //store 2nd axis points in point array
                            qmesh.Vertices.Add(axis[(k + 1) % 4][i]); //also add 2nd axis points to mesh
                            qindex[0, i] = count++;                   //store indicies
                        }


                        for (int i = 1; i < quad.GetLength(0); i++)
                        {
                            if (i < axis[k].Count)              // add axis vertex
                            {
                                quad[i, 0] = axis[k][i];        //store 1st axis points in point array
                                qmesh.Vertices.Add(axis[k][i]); //also add 1st axis points to mesh
                                qindex[i, 0] = count++;         //store indicies
                            }


                            int counter = 0;

                            List <Polyline> currentStrip = new List <Polyline>();
                            // for each column attempt to locate a new vertex in the grid
                            for (int j = 1; j < quad.GetLength(1); j++)
                            {
                                // if quad[i - 1, j] doesn't exist, try to add it and continue (or else break the current row)
                                if (quad[i - 1, j] == new Point3d())
                                {
                                    if (j < 2)
                                    {
                                        break;
                                    }

                                    CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j - 1], quad[i - 1, j - 2], R);

                                    if (isct.Count > 0)
                                    {
                                        quad[i - 1, j] = isct[0].PointB;
                                        qmesh.Vertices.Add(quad[i - 1, j]);
                                        qindex[i - 1, j] = count++;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                // if quad[i, j - 1] doesn't exist, try to create quad[i, j] by projection and skip mesh face creation
                                if (quad[i, j - 1] == new Point3d())
                                {
                                    if (i < 2)
                                    {
                                        break;
                                    }

                                    CurveIntersections isct = this.ArcIntersect(S, quad[i - 1, j], quad[i - 2, j], R);

                                    if (isct.Count > 0)
                                    {
                                        quad[i, j] = isct[0].PointB;
                                        qmesh.Vertices.Add(quad[i, j]);
                                        qindex[i, j] = count++;

                                        continue;
                                    }
                                }

                                // construct a sphere at each neighbouring vertex ([i,j-1] and [i-1,j]) and intersect

                                Sphere sph1 = new Sphere(quad[i, j - 1], R);
                                Sphere sph2 = new Sphere(quad[i - 1, j], R);
                                Circle cir;

                                if (Intersection.SphereSphere(sph1, sph2, out cir) == SphereSphereIntersection.Circle)
                                {
                                    CurveIntersections cin = Intersection.CurveSurface(NurbsCurve.CreateFromCircle(cir), S, 0.01, 0.01);// intersect circle with surface

                                    // attempt to find the new vertex (i.e not [i-1,j-1])

                                    foreach (IntersectionEvent ie in cin)
                                    {
                                        if ((ie.PointA - quad[i - 1, j - 1]).Length > 0.2 * R)  // compare with a tolerance, rather than exact comparison

                                        {
                                            quad[i, j] = ie.PointA;
                                            qmesh.Vertices.Add(quad[i, j]);
                                            qindex[i, j] = count++;

                                            Point3d[] facePt = new Point3d[] { quad[i, j], quad[i - 1, j], quad[i - 1, j - 1], quad[i, j - 1] };

                                            Sold.ClosestPoint(quad[i, j], out double u1, out double v1);
                                            Sold.ClosestPoint(quad[i - 1, j], out double u2, out double v2);
                                            Sold.ClosestPoint(quad[i - 1, j - 1], out double u3, out double v3);
                                            Sold.ClosestPoint(quad[i, j - 1], out double u4, out double v4);

                                            double tolerance = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance * 10;
                                            bool[] flag      = new bool[] {
                                                Sold.PointAt(u1, v1).DistanceTo(quad[i, j]) < tolerance,
                                                Sold.PointAt(u2, v2).DistanceTo(quad[i - 1, j]) < tolerance,
                                                Sold.PointAt(u3, v3).DistanceTo(quad[i - 1, j - 1]) < tolerance,
                                                Sold.PointAt(u4, v4).DistanceTo(quad[i, j - 1]) < tolerance
                                            };



                                            if (flag[0] && flag[1] && flag[2] && flag[3])
                                            {
                                                qmesh.Faces.AddFace(qindex[i, j], qindex[i - 1, j], qindex[i - 1, j - 1], qindex[i, j - 1]);// create quad-face
                                                currentStrip.Add(new Polyline()
                                                {
                                                    quad[i, j], quad[i - 1, j], quad[i - 1, j - 1], quad[i, j - 1], quad[i, j]
                                                });
                                                counter++;
                                            }
                                            else if (flag[0] || flag[1] || flag[2] || flag[3])
                                            {
                                                Polyline temp = new Polyline()
                                                {
                                                    quad[i, j], quad[i - 1, j], quad[i - 1, j - 1], quad[i, j - 1]
                                                };
                                                Polyline trimmedTemp = new Polyline();
                                                //temp = new Polyline() { quad[i, j], quad[i - 1, j], quad[i - 1, j - 1], quad[i, j - 1], quad[i, j] };

                                                double        t = R * 0.1;
                                                HashSet <int> intersectedSurfaceEdgeId = new HashSet <int>();


                                                for (int l = 0; l < 4; l++)
                                                {
                                                    //If point is ons surface
                                                    Sold.ClosestPoint(temp[l], out double cpu, out double cpv);
                                                    if (Sold.PointAt(cpu, cpv).DistanceTo(temp[l]) < Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)
                                                    {
                                                        trimmedTemp.Add(temp[l]);
                                                    }


                                                    //Intersect line segment with closed brep
                                                    Line faceSegment = new Line(temp[l], temp[MathUtil.Wrap(l + 1, 4)]);

                                                    Point3d[] meshLinePts = Intersection.MeshLine(cutter, faceSegment, out int[] faceIds);
                                                    if (meshLinePts.Length > 0)
                                                    {
                                                        trimmedTemp.Add(meshLinePts[0]);
                                                    }
                                                }


                                                trimmedTemp.Close();
                                                //cuts.Add(trimmedTemp);
                                            }

                                            break;
                                        }
                                    }

                                    if (preview.Enabled)
                                    {
                                        preview.Clear();
                                        preview.AddMesh(mesh);
                                        preview.AddMesh(qmesh);
                                        preview.Redraw();
                                    }
                                } //if sphere intersection
                            }     //for j

                            if (currentStrip.Count > 0)
                            {
                                strips[k].Add(currentStrip);
                            }
                        }//for i



                        mesh.Append(qmesh);// add local mesh to target
                        fourMeshes[k] = qmesh;
                    }//for k



                    //----------------------------------------------------------------------------------------------------------//
                    //Output



                    mesh.Weld(Math.PI);
                    mesh.Compact();
                    mesh.Normals.ComputeNormals();

                    DA.SetData(0, mesh);
                    DA.SetDataTree(1, NGonsCore.GrasshopperUtil.IE2(axis, 0));

                    this.PreparePreview(mesh, DA.Iteration, null, true, null, mesh.GetEdges());
                    //DA.SetDataList(2, cuts);
                    //DA.SetDataTree(3, NGonsCore.GrasshopperUtil.IE4(patches.ToList(), 0));
                    //DA.SetDataList(4, fourMeshes);
                    //DA.SetDataTree(5, GrasshopperUtil.IE3(strips, 0));

                    preview.Clear();
                }catch (Exception e) {
                    GrasshopperUtil.Debug(e);
                }
            }