Пример #1
0
        static void Main(string[] args)
        {
            ComputeServer.AuthToken = Rhino.Compute.AuthToken.Get();

            Curve curveA = Curve.CreateControlPointCurve(new Point3d[] {
                new Point3d(0.0, 0.0, 0.0),
                new Point3d(0.0, 0.5, -0.5),
                new Point3d(0.0, 1.0, 0.0)
            });
            Curve curveB = Curve.CreateControlPointCurve(new Point3d[] {
                new Point3d(1.0, 0.0, 0.0),
                new Point3d(1.0, 0.3, 0.6),
                new Point3d(1.0, 0.5, 0.0),
                new Point3d(1.0, 0.7, 0.8),
                new Point3d(1.0, 1.0, 0.0)
            });

            NurbsSurface ruled = NurbsSurface.CreateRuledSurface(curveA, curveB);

            Mesh mesh1 = MeshCompute.CreateFromSurface(ruled);

            Rhino.Compute.ObjExport.ExportMeshesToObj("ruled_mesh_default.obj", new Mesh[] { mesh1 });

            MeshingParameters meshingParameters = new MeshingParameters();

            meshingParameters.MaximumEdgeLength = 0.1;
            Mesh mesh2 = MeshCompute.CreateFromSurface(ruled, meshingParameters);

            Rhino.Compute.ObjExport.ExportMeshesToObj("ruled_mesh_refined1.obj", new Mesh[] { mesh2 });

            meshingParameters.MaximumEdgeLength = 0.05;
            Mesh mesh3 = MeshCompute.CreateFromSurface(ruled, meshingParameters);

            Rhino.Compute.ObjExport.ExportMeshesToObj("ruled_mesh_refined2.obj", new Mesh[] { mesh3 });
        }
Пример #2
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)
        {
            double      num  = 0;
            List <Brep> list = new List <Brep>();

            if (DA.GetDataList <Brep>(0, list) && DA.GetData <double>(1, ref num))
            {
                Brep[] brepArray = null;
                brepArray = Brep.CreateBooleanUnion(list.ToArray(), 0.1);
                MeshingParameters meshingParameters = new MeshingParameters
                {
                    MaximumEdgeLength = num
                };
                Mesh[] meshArray = Mesh.CreateFromBrep(brepArray[0], meshingParameters);
                Mesh   msh       = new Mesh();
                int    num3      = meshArray.Length - 1;
                for (int i = 0; i <= num3; i++)
                {
                    msh.Append(meshArray[i]);
                }
                msh.Vertices.CullUnused();
                msh.Vertices.CombineIdentical(true, true);
                msh.UnifyNormals();
                msh = this.triangulation(msh);
                DA.SetData(0, msh);
            }
        }
Пример #3
0
        public static void BuildPreview
        (
            DB.Element element, MeshingParameters meshingParameters, DB.ViewDetailLevel DetailLevel,
            out Rhino.Display.DisplayMaterial[] materials, out Mesh[] meshes, out Curve[] wires
        )
        {
            DB.Options options = null;
            using (var geometry = element?.GetGeometry(DetailLevel == DB.ViewDetailLevel.Undefined ? DB.ViewDetailLevel.Medium : DetailLevel, out options)) using (options)
                {
                    if (geometry is null)
                    {
                        materials = null;
                        meshes    = null;
                        wires     = null;
                    }
                    else
                    {
                        var categoryMaterial = element.Category?.Material.ToRhino(null);
                        var elementMaterial  = geometry.MaterialElement.ToRhino(categoryMaterial);

                        meshes    = geometry.GetPreviewMeshes(meshingParameters).Where(x => x is object).ToArray();
                        wires     = geometry.GetPreviewWires().Where(x => x is object).ToArray();
                        materials = geometry.GetPreviewMaterials(element.Document, elementMaterial).Where(x => x is object).ToArray();

                        foreach (var mesh in meshes)
                        {
                            mesh.Normals.ComputeNormals();
                        }
                    }
                }
        }
Пример #4
0
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public PointFunction1(Mesh.T_POINTS apoints, Array <INDEX_3> afaces, MeshingParameters amp, double ah)
        {
            this.points = apoints;
            this.faces  = afaces;
            this.mp     = amp;
            h           = ah;
        }
            /// <summary>
            /// Shorthand tool for map mesh objects.
            /// </summary>
            /// <param name="Map_Srf">A NURBS surface to mesh.</param>
            /// <param name="Increment">the maximum dimension between vertices.</param>
            /// <returns>the map mesh object.</returns>
            public static Mesh Create_Map_Mesh(IEnumerable <Brep> Map_Srf, double Increment)
            {
                Mesh Map_Mesh        = new Mesh();
                MeshingParameters mp = new MeshingParameters();

                mp.MaximumEdgeLength = Increment;
                mp.MinimumEdgeLength = Increment;
                mp.SimplePlanes      = false;
                mp.JaggedSeams       = false;
                Brep[] Srfs = Map_Srf.ToArray <Brep>();
                for (int i = 0; i < Map_Srf.ToArray <Brep>().Length; i++)
                {
                    Mesh           m = Rhino.Geometry.Mesh.CreateFromBrep(Srfs[i], mp)[0];
                    Point3d        pt;
                    double         s, t;
                    ComponentIndex ci;
                    Vector3d       Snormal;
                    Srfs[i].ClosestPoint(m.Vertices[m.Vertices.Count() / 2], out pt, out ci, out s, out t, 1.0f, out Snormal);
                    Vector3d Mnormal = m.Normals[m.Vertices.Count() / 2];
                    if ((Snormal.X * Mnormal.X + Snormal.Y * Mnormal.Y + Snormal.Z * Mnormal.Z) < 0)
                    {
                        m.Flip(true, true, true);
                    }
                    Map_Mesh.Append(m);
                }

                return(Map_Mesh);
            }
        // Breps
        public static SpeckleBrep ToSpeckle(this Brep brep)
        {
            var joinedMesh = new Mesh();

            if (SpeckleRhinoConverter.SetBrepDisplayMesh)
            {
                MeshingParameters mySettings;
#if R6
                mySettings = new MeshingParameters(0);
#else
                mySettings = MeshingParameters.Coarse;

                mySettings.SimplePlanes      = true;
                mySettings.RelativeTolerance = 0;
                mySettings.GridAspectRatio   = 6;
                mySettings.GridAngle         = Math.PI;
                mySettings.GridAspectRatio   = 0;
                mySettings.SimplePlanes      = true;
#endif

                Mesh.CreateFromBrep(brep, mySettings).All(meshPart => { joinedMesh.Append(meshPart); return(true); });
            }

            return(new SpeckleBrep(displayValue: SpeckleRhinoConverter.SetBrepDisplayMesh?joinedMesh.ToSpeckle() : null, rawData: JsonConvert.SerializeObject(brep), provenance: "Rhino", properties: brep.UserDictionary.ToSpeckle(root: brep)));
        }
Пример #7
0
        // Place calls to RhinoCommon in a separate function from main so the jit doesn't
        // try to load RhinoCommon until after RhinoLib.LaunchInProcess is called
        static void MeshABrep()
        {
            var sphere = new Sphere(Point3d.Origin, 12);
            var brep   = sphere.ToBrep();
            var mp     = new MeshingParameters(0.5);
            var mesh   = Mesh.CreateFromBrep(brep, mp);

            Console.WriteLine($"Mesh with {mesh[0].Vertices.Count} vertices created");
        }
Пример #8
0
        public virtual int GenerateMesh(ref Mesh mesh, MeshingParameters mparam)
        {
            if (mesh == null)
            {
                return(1);
            }

            if (mparam.perfstepsstart <= (int)MESHING_STEP.MESHCONST_MESHVOLUME)
            {
                multithread.task = "Volume meshing";

                MESHING3_RESULT res = MeshVolume(mparam, mesh);

                if (res != MESHING3_RESULT.MESHING3_OK)
                {
                    return(1);
                }

                if (multithread.terminate)
                {
                    return(0);
                }

                RemoveIllegalElements(mesh);
                if (multithread.terminate)
                {
                    return(0);
                }

                MeshQuality3d(mesh);
            }


            if (multithread.terminate || mparam.perfstepsend <= (int)MESHING_STEP.MESHCONST_MESHVOLUME)
            {
                return(0);
            }


            if (mparam.perfstepsstart <= (int)MESHING_STEP.MESHCONST_OPTVOLUME)
            {
                multithread.task = "Volume optimization";

                OptimizeVolume(mparam, mesh);
                if (multithread.terminate)
                {
                    return(0);
                }
            }

            return(0);
        }
Пример #9
0
        private List <Rhino.Geometry.Mesh> CheckOrCreateMesh(Brep brep, MeshingParameters mp)
        {
            List <Rhino.Geometry.Mesh> ret = null;

            if (brep != null)
            {
                ret = new List <Rhino.Geometry.Mesh>(
                    Rhino.Geometry.Mesh.CreateFromBrep(brep, mp));
            }

            // no mesh/brep face found
            return(ret);
        }
        // Breps
        public static SpeckleBrep ToSpeckle(this Brep brep)
        {
            var joinedMesh = new Mesh();

            MeshingParameters mySettings;

            mySettings = new MeshingParameters(0);

            Mesh.CreateFromBrep(brep, mySettings).All(meshPart => { joinedMesh.Append(meshPart); return(true); });


            return(new SpeckleBrep(displayValue: joinedMesh.ToSpeckle(), rawData: JsonConvert.SerializeObject(brep), provenance: "Rhino", properties: brep.UserDictionary.ToSpeckle(root: brep)));
        }
Пример #11
0
 public void DrawViewportMeshes(GH_PreviewMeshArgs args)
 {
     if (args.Pipeline.SupportsShading)
     {
         if (this._mesh == null)
         {
             if (this.m_value == null)
             {
                 return;
             }
             MeshingParameters @params = args.MeshingParameters;
             if (@params == null)
             {
                 return;
             }
             if (this._extrusion == null)
             {
                 // Set extrusion
                 List <Brep> breps = Utilities.CreateSectionSweeps(this.Value);
                 _extrusion = Brep.JoinBreps(breps, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)[0];
             }
             Mesh[] rc = Mesh.CreateFromBrep(this._extrusion, @params);
             if (rc == null)
             {
                 this._mesh = new Mesh();
             }
             else if (rc.Length == 1)
             {
                 this._mesh = rc[0];
             }
             else
             {
                 this._mesh = new Mesh();
                 Mesh[] array = rc;
                 for (int j = 0; j < array.Length; j++)
                 {
                     Mesh i = array[j];
                     this._mesh.Append(i);
                 }
             }
         }
         if (this._mesh == null)
         {
             return;
         }
         args.Pipeline.DrawMeshShaded(this._mesh, args.Material);
     }
 }
Пример #12
0
        public Mesh[] TryGetPreviewMeshes(MeshingParameters parameters = default)
        {
            if (parameters is object && !ReferenceEquals(meshingParameters, parameters))
            {
                meshingParameters = parameters;
                if (geometryPreview is object)
                {
                    if (geometryPreview.MeshingParameters?.RelativeTolerance != meshingParameters.RelativeTolerance)
                    {
                        GeometryPreview = null;
                    }
                }
            }

            return(GeometryPreview.meshes);
        }
Пример #13
0
        public static Mesh FromFacesToMesh(List <Face> faces)
        {
            Mesh mesh = new Mesh();

            MeshingParameters settings = new MeshingParameters();

            settings.SimplePlanes = true;

            foreach (Face face in faces)
            {
                Brep brep = FromFaceToBrep(face);
                mesh.Append(Mesh.CreateFromBrep(brep, settings)[0]);
            }

            return(mesh);
        }
Пример #14
0
        private void test01_click(object sender, RibbonControlEventArgs e)
        {
            //Open Excel Worksheet
            Microsoft.Office.Interop.Excel.Worksheet activeWorksheet = Globals.RhinoInsideAddIn.Application.ActiveSheet;


            try
            {
                var sphere = new Sphere(Point3d.Origin, 12);
                var brep   = sphere.ToBrep();
                var mp     = new MeshingParameters(0.5);
                var mesh   = Mesh.CreateFromBrep(brep, mp);
                System.Windows.Forms.MessageBox.Show($"Mesh with {mesh[0].Vertices.Count} vertices created");
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }
        Mesh[] Meshes(MeshingParameters meshingParameters)
        {
            if (meshes is null && IsValid)
            {
                meshes = Enumerable.Repeat(Value, 1).GetPreviewMeshes(meshingParameters).ToArray();

                if (Value.IsElementGeometry && Document?.GetElement(Reference) is DB.Instance instance)
                {
                    var xform = instance.GetTransform().ToTransform();
                    foreach (var mesh in meshes)
                    {
                        mesh.Transform(xform);
                    }
                }

                foreach (var mesh in meshes)
                {
                    mesh.Normals.ComputeNormals();
                }
            }

            return(meshes);
        }
        public static Mesh ConvertBrepToTriMeshSolid(Brep brep)
        {
            // convert to mesh
            MeshingParameters mparams = MeshingParameters.Minimal;

            mparams.JaggedSeams  = false;
            mparams.SimplePlanes = true;

            Mesh[] ms = Mesh.CreateFromBrep(brep, mparams);
            Mesh   m  = new Mesh();

            m.Append(ms);

            // test if mesh is closed
            if (!m.IsClosed)
            {
                // try fill holes
                m.FillHoles();

                // if not succesfull return null
                if (!m.IsClosed)
                {
                    return(null);
                }
            }

            // weld mesh (collapse verticies)
            m.Weld(Math.PI);

            // triangulate all faces
            m.Faces.ConvertQuadsToTriangles();

            m.CollapseFacesByEdgeLength(false, GhSA.Units.Tolerance);

            return(m);
        }
Пример #17
0
            public SurfaceSource(IEnumerable <Brep> Surfaces, List <String> CodeList, int el_m, int SrcID, Phase_Regime ph)
                : base(new double[8] {
                0, 0, 0, 0, 0, 0, 0, 0
            }, new Point3d(0, 0, 0), ph, SrcID)
            {
                samplespermeter = el_m;

                Srfs    = Surfaces.ToList <Brep>();
                Samples = new Point3d[Srfs.Count][];

                MeshingParameters mp = new MeshingParameters();

                mp.MaximumEdgeLength = 1.0 / (double)samplespermeter;
                mp.MinimumEdgeLength = 1.0 / (double)samplespermeter;

                Sub_A      = new double[Srfs.Count];
                SubDomains = new double[Srfs.Count][];
                T          = new Topology[Srfs.Count];

                //for(int i = 0; i < Curves.Count; i++)
                System.Threading.Tasks.Parallel.For(0, Srfs.Count, ips =>
                {
                    int i = (int)ips;


                    //Divide each curve up in ~equal length segments.
                    Mesh[] m        = Mesh.CreateFromBrep(Srfs[i], mp);
                    BoundingBox Box = m[0].GetBoundingBox(true);
                    for (int j = 1; j < m.Length; j++)
                    {
                        Box.Union(m[j].GetBoundingBox(true));
                    }
                    T[i] = new Topology(Utilities.PachTools.RPttoHPt(Box.Min), Utilities.PachTools.RPttoHPt(Box.Max));

                    List <Point3d> pts = new List <Point3d>();
                    SubDomains[i]      = new double[m[i].Faces.Count + 1];
                    for (int j = 0; j < m[i].Faces.Count; j++)
                    {
                        double u, v;
                        ComponentIndex ci;
                        Point3d no;
                        Vector3d V;
                        Point3d A = m[i].Vertices[m[i].Faces[j].A];
                        Srfs[i].ClosestPoint(A, out no, out ci, out u, out v, 1, out V);
                        A        += V;
                        Point3d B = m[i].Vertices[m[i].Faces[j].B];
                        Srfs[i].ClosestPoint(B, out no, out ci, out u, out v, 1, out V);
                        B        += V;
                        Point3d C = m[i].Vertices[m[i].Faces[j].C];
                        Srfs[i].ClosestPoint(C, out no, out ci, out u, out v, 1, out V);
                        C        += V;
                        Point3d D = m[i].Vertices[m[i].Faces[j].D];
                        Srfs[i].ClosestPoint(D, out no, out ci, out u, out v, 1, out V);
                        D += V;

                        if (m[i].Faces[j].IsQuad)
                        {
                            Hare.Geometry.Point[] poly = new Hare.Geometry.Point[4];
                            poly[0] = new Hare.Geometry.Point(A.X, A.Y, A.Z);
                            poly[1] = new Hare.Geometry.Point(B.X, B.Y, B.Z);
                            poly[2] = new Hare.Geometry.Point(C.X, C.Y, C.Z);
                            poly[3] = new Hare.Geometry.Point(D.X, D.Y, D.Z);
                            T[i].Add_Polygon(poly);
                        }
                        else
                        {
                            Hare.Geometry.Point[] poly = new Hare.Geometry.Point[3];
                            poly[0] = new Hare.Geometry.Point(A.X, A.Y, A.Z);
                            poly[1] = new Hare.Geometry.Point(B.X, B.Y, B.Z);
                            poly[2] = new Hare.Geometry.Point(C.X, C.Y, C.Z);
                            T[i].Add_Polygon(poly);
                        }

                        pts.Add(m[i].Faces[j].IsQuad ? new Point3d(A.X + B.X + C.X + D.X, A.Y + B.Y + C.Y + D.Y, A.Z + B.Z + C.Z + D.Z) / 4 : new Point3d(A.X + B.X + C.X, A.Y + B.Y + C.Y, A.Z + B.Z + C.Z) / 3);

                        SubDomains[i][j + 1] = Sub_A[i] += T[i].Polygon_Area(j);
                    }
                    Samples[i] = pts.ToArray();
                });

                Domains     = new double[Srfs.Count + 1];
                DomainLevel = new double[Srfs.Count][];
                DomainPower = new double[Srfs.Count][];
                Total_A     = 0;

                for (int i = 0; i < Srfs.Count; i++)
                {
                    for (int j = 0; j < SubDomains[i].Length; j++)
                    {
                        SubDomains[i][j] /= Sub_A[i];
                    }
                    double A = Srfs[i].GetArea();
                    Domains[i + 1] = Total_A += A;
                    DomainLevel[i] = Utilities.PachTools.DecodeSourcePower(CodeList[i]);
                    DomainPower[i] = new double[8];
                    double PowerMod = A;
                    for (int oct = 0; oct < 8; oct++)
                    {
                        DomainPower[i][oct] = 1E-12 * Math.Pow(10, .1 * DomainLevel[i][oct]) / PowerMod;
                    }
                }

                for (int i = 0; i < Domains.Length; i++)
                {
                    Domains[i] /= Total_A;
                }
            }
        /*internal*/
        public static IEnumerable <Mesh> GetPreviewMeshes
        (
            this IEnumerable <DB.GeometryObject> geometries,
            MeshingParameters meshingParameters
        )
        {
            foreach (var geometry in geometries)
            {
                if (geometry.Visibility != DB.Visibility.Visible)
                {
                    continue;
                }

                switch (geometry)
                {
                case DB.GeometryInstance instance:
                {
                    var xform = instance.Transform.ToTransform();
                    foreach (var g in instance.SymbolGeometry.GetPreviewMeshes(meshingParameters))
                    {
                        g?.Transform(xform);
                        yield return(g);
                    }
                    break;
                }

                case DB.Mesh mesh:
                {
                    if (mesh.NumTriangles <= 0)
                    {
                        continue;
                    }

                    var f = Geometry.Raw.RawDecoder.ToRhino(mesh);
                    UnitConverter.Scale(f, UnitConverter.ToRhinoUnits);

                    yield return(f);

                    break;
                }

                case DB.Face face:
                {
                    var faceMesh = face.Triangulate(meshingParameters.LevelOfDetail());
                    var f        = Geometry.Raw.RawDecoder.ToRhino(faceMesh);
                    UnitConverter.Scale(f, UnitConverter.ToRhinoUnits);

                    yield return(f);

                    break;
                }

                case DB.Solid solid:
                {
                    if (solid.Faces.IsEmpty)
                    {
                        continue;
                    }

                    var  solidFaces           = solid.Faces.OfType <DB.Face>();
                    bool useMultipleMaterials = solidFaces.HasMultipleMaterials();
                    var  facesMeshes          = useMultipleMaterials ? null : new List <Mesh>(solid.Faces.Size);
                    foreach (var face in solidFaces)
                    {
                        var faceMesh = face.Triangulate(meshingParameters.LevelOfDetail());
                        var f        = Geometry.Raw.RawDecoder.ToRhino(faceMesh);
                        UnitConverter.Scale(f, UnitConverter.ToRhinoUnits);

                        if (facesMeshes is null)
                        {
                            yield return(f);
                        }
                        else if (f is object)
                        {
                            facesMeshes.Add(f);
                        }
                    }

                    if (facesMeshes is object)
                    {
                        if (facesMeshes.Count > 0)
                        {
                            var mesh = new Mesh();

                            mesh.Append(facesMeshes);
                            yield return(mesh);
                        }
                        else
                        {
                            yield return(null);
                        }
                    }
                    break;
                }
                }
            }
        }
Пример #19
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)
        {
            #region updateInputs
            //if (!cap && this.Params.Input.Count ==7)
            //{
            //    this.Params.Input[5].RemoveAllSources();
            //    this.Params.UnregisterInputParameter(this.Params.Input[5]);
            //    this.Params.Input[6].RemoveAllSources();
            //    this.Params.UnregisterInputParameter(this.Params.Input[6]);

            //    Params.OnParametersChanged();
            //}
            //if (cap && this.Params.Input.Count == 5)
            //{
            //    this.Params.RegisterInputParam(new Param_Colour
            //    {
            //        Name = "MinColor",
            //        NickName = "MinColor",
            //        Description = "MinColor",
            //        Access = GH_ParamAccess.item,
            //        Optional = true
            //    });
            //    this.Params.RegisterInputParam(new Param_Colour
            //    {
            //        Name = "MaxColor",
            //        NickName = "MaxColor",
            //        Description = "MinColor",
            //        Access = GH_ParamAccess.item,
            //        Optional = true
            //    });

            //    Params.OnParametersChanged();
            //}

            #endregion updateInputs

            //bool caps = DA.Fetch<bool>("Cap");
            Color?maxColor   = DA.Fetch <Color?>(i_inputSelecterMax);
            Color?minColor   = DA.Fetch <Color?>(i_inputSelectorMin);
            var   allResults = DA.FetchTree <GH_Number>("Results");
            var   grids      = DA.FetchList <Grid>("Grids");
            //var gradientRange = DA.Fetch<string>("GradientRange");
            //int maxCount = DA.Fetch<int>("MaxCount");
            int maxCount = 200;
            //var inStepSize = DA.Fetch<int>("StepSize");
            //var inSteps = DA.Fetch<int>("Steps");
            InputSelector inputSelector = DA.Fetch <InputSelector>("_Section Type");

            double globalMin = double.MaxValue;
            double globalMax = double.MinValue;

            for (int g = 0; g < grids.Count; g++)
            {
                globalMin = Math.Min(globalMin, ((List <GH_Number>)allResults.get_Branch(g)).Select(r => r.Value).Min());
                globalMax = Math.Max(globalMax, ((List <GH_Number>)allResults.get_Branch(g)).Select(r => r.Value).Max());
            }


            if (inputSelector == null)
            {
                inputSelector = new InputSelector(10, globalMin, globalMax);
            }



            if (allResults.Branches.Count != grids.Count)
            {
                throw new Exception("Grid count doesnt match results");
            }


            //var colorDomain = Misc.AutoDomain(gradientRange, allResults);
            //Rhino.RhinoApp.WriteLine($"{range}  ->  {domain[0]} to {domain[1]}");

            GH_GradientControl gc;
            try
            {
                gc = (GH_GradientControl)Params.Input[i_inputGradient].Sources[0].Attributes.GetTopLevel.DocObject;
            }
            catch (System.ArgumentOutOfRangeException)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Remember to add a gradient component in grasshopper!");
                gc = null;
            }

            GradientParser gp = new GradientParser(gc)
            {
                //Cap = caps,
                AboveMax = maxColor == default(Color) ? null : maxColor,
                BelowMin = minColor == default(Color) ? null : minColor,
                //Min = domain[0],
                //Max = domain[1],
                Reverse = Params.Input[i_inputGradient].Reverse
            };



            IDictionary <string, Color> colorDescriptions = new Dictionary <string, Color>();
            IDictionary <string, int>   colorPaths        = new Dictionary <string, int>();



            #region coloredMesh
            var outMeshes = new List <Mesh>();



            for (int i = 0; i < grids.Count; i++)
            {
                //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"Mesh vertices: {grids[i].SimMesh.Vertices.Count}, colors = {gp.GetColors(allResults.Branches[i].Select(p => p.Value).ToArray()).Length} f");


                outMeshes.Add(grids[i].GetColoredMesh(gp.GetColors(allResults.Branches[i].Select(p => p.Value).ToArray())));

                Mesh      m      = grids[i].SimMesh;
                Point3d[] points = grids[i].SimPoints.ToArray();
                outMeshes[outMeshes.Count - 1].Translate(0, 0, Units.ConvertFromMeter(0.001));
            }


            DA.SetDataList(0, outMeshes);

            #endregion coloredMesh



            #region layeredMesh

            if (grids[0].UseCenters == true)
            {
                return;
            }

            //Outputs
            GH_Structure <GH_Mesh>  oLayeredMeshes = new GH_Structure <GH_Mesh>();
            List <GH_Mesh>          previewMeshes  = new List <GH_Mesh>();
            List <GH_Plane>         outPlanes      = new List <GH_Plane>();
            GH_Structure <GH_Curve> outCurves      = new GH_Structure <GH_Curve>();

            GH_Structure <GH_String> outValues = new GH_Structure <GH_String>();
            GH_Structure <GH_Colour> outColors = new GH_Structure <GH_Colour>();

            const double SCALAR = 1; // don't change.



            if (((GH_Structure <GH_Number>)gc.Params.Input[1].VolatileData)[0][0].Value == 1)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "The gradient connected has 1 as max. Is that on purpose? Check the inputs of your gradient component." +
                                       $"\nI suggest you set your max somewhere around {globalMax:0.0}");
            }


            for (int g = 0; g < grids.Count; g++)
            {
                //GH_Structure<GH_Curve> curves = new GH_Structure<GH_Curve>();
                Grid grid      = grids[g];
                Mesh inputMesh = grids[g].SimMesh.DuplicateMesh();
                //Mesh meshToCut = grids[g].SimMesh;

                List <double> results = ((List <GH_Number>)allResults.get_Branch(g)).Select(r => r.Value).ToList();

                if (grids[g].UseCenters == true)
                {
                    results = RTreeSolver.FindClosestWeightedValues(grids[g], results, true).ToList();
                    // ADD CONVERSION TODO:
                }

                inputMesh.Normals.ComputeNormals();

                Vector3f normal = inputMesh.FaceNormals[0];

                Plane basePlane = new Plane(inputMesh.Vertices[0], normal);

                Transform ProjectToBase = Transform.PlanarProjection(basePlane);

                Plane cuttingPlane = new Plane(basePlane);

                Mesh meshToCut = CreateMeshToBeCut(SCALAR, inputMesh, results, cuttingPlane);

                previewMeshes.Add(new GH_Mesh(inputMesh));

                MeshingParameters mp = new MeshingParameters(0);

                List <Mesh> layeredMeshesThisGrid = new List <Mesh>();


                double valueForSmallAreas = double.MinValue;

                double resultsMin = results.Min();

                foreach (var item in inputSelector)
                {
                    if (resultsMin >= item)
                    {
                        valueForSmallAreas = item;
                        break;
                    }
                }

                //Color col = gp.GetColors(new List<double>() { inputSelector.Min.Value })[0];
                Color col = gp.GetColors(new List <double>()
                {
                    gp.BelowMin.HasValue&& inputSelector.Min.Value <= gp.Min ? resultsMin > gp.Min ? valueForSmallAreas : double.MinValue :  inputSelector.Min.Value
                })[0];

                Polyline[] outlinePolylines = inputMesh.GetNakedEdges();

                PolylineCurve[] curvesFromOutline = new PolylineCurve[outlinePolylines.Length];

                for (int i = 0; i < outlinePolylines.Length; i++)
                {
                    curvesFromOutline[i] = new PolylineCurve(outlinePolylines[i]);
                    curvesFromOutline[i].Transform(ProjectToBase);
                }


                Mesh meshFromCurves = GetMeshFromCurves(curvesFromOutline, mp, in col);

                GH_Path startPath = new GH_Path(g, -1);
                oLayeredMeshes.Append(new GH_Mesh(meshFromCurves), startPath);


                string lessThanKey = gp.BelowMin.HasValue && inputSelector.Min.Value < gp.Min ? $"<{gp.Min:0.0}" : $"<{inputSelector.Min.Value:0.0}";
                if (!colorDescriptions.ContainsKey(lessThanKey) && inputSelector.First() < gp.Min)
                {
                    colorDescriptions.Add(lessThanKey, col);
                    colorPaths.Add(lessThanKey, -1);
                }

                ////outColors.Append(new GH_Colour(col), startPath);
                ////outValues.Append(new GH_Number(double.MinValue), startPath);

                //Mesh[] meshesFromCurves = GetMeshesFromCurves(curvesFromOutline, mp, in col);

                //oLayeredMeshes.AppendRange(meshesFromCurves.Select(m => new GH_Mesh(m)), new GH_Path(g, -1));



                int    cuttingCount  = 0;
                double previousValue = 0;

                foreach (double currentValue in inputSelector)
                {
                    if (cuttingCount > maxCount)
                    {
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Too many steps... I reached  {maxCount} and then stopped");
                        break;
                    }

                    if (gp.BelowMin.HasValue && currentValue < gp.Min)
                    {
                        continue;
                    }


                    if (currentValue > results.Max())
                    {
                        break;
                    }


                    // Create planes

                    Vector3f moveUpVector = normal * (float)((currentValue - previousValue) * SCALAR);

                    Transform t = Transform.Translation(moveUpVector);

                    GH_Path path = new GH_Path(g, cuttingCount);

                    cuttingPlane.Transform(t);

                    outPlanes.Add(new GH_Plane(cuttingPlane));



                    // Create boundary intersected curves

                    Curve[] intersectedCurves = GetIntersectedCurves(inputMesh, cuttingPlane);



                    if (intersectedCurves != null)
                    {
                        outCurves.AppendRange(intersectedCurves.Select(c => new GH_Curve(c.DuplicateCurve())), path);

                        foreach (var curve in intersectedCurves)
                        {
                            curve.Transform(ProjectToBase);
                        }


                        // Create meshes

                        col = gp.GetColors(new List <double>()
                        {
                            currentValue
                        })[0];



                        meshFromCurves = GetMeshFromCurves(intersectedCurves, mp, in col);

                        meshFromCurves.Transform(Transform.Translation(0, 0, (cuttingCount + 1) * Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance * 12.0));



                        if (meshFromCurves != null)
                        {
                            //oLayeredMeshes.AppendRange(meshesFromCurves.Select(m => new GH_Mesh(m)), path);
                            oLayeredMeshes.Append(new GH_Mesh(meshFromCurves), path);
                            string key = currentValue >= gp.Max.Value ? $">{currentValue:0.0}" : $"{currentValue:0.0}";
                            if (!colorDescriptions.ContainsKey(key))
                            {
                                colorDescriptions.Add(key, col);
                                colorPaths.Add(key, cuttingCount);
                            }
                        }

                        if (currentValue >= gp.Max.Value)
                        {
                            break;
                        }
                    }



                    previousValue = currentValue;

                    cuttingCount++;
                }
            }

            foreach (KeyValuePair <string, Color> valuePair in colorDescriptions)
            {
                GH_Path path = new GH_Path(colorPaths[valuePair.Key]);


                outColors.Append(new GH_Colour(valuePair.Value), path);
                outValues.Append(new GH_String(valuePair.Key), path);
            }



            DA.SetDataTree(1, oLayeredMeshes);
            DA.SetDataTree(2, outCurves);
            DA.SetDataList("Planes", outPlanes);
            DA.SetDataList("TempMeshes", previewMeshes);
            DA.SetDataTree(6, outValues);
            DA.SetDataTree(5, outColors);

            #endregion layeredMesh
        }
Пример #20
0
 private Mesh GetMeshFromCurves(Curve[] intersectedCurves, MeshingParameters mp, in Color col)
Пример #21
0
 Preview(GeometricElement element)
 {
     geometricElement  = element;
     clippingBox       = element.ClippingBox;
     MeshingParameters = element.meshingParameters;
 }
 static double LevelOfDetail(this MeshingParameters value) => value?.RelativeTolerance ?? 0.15;
Пример #23
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
            // ---
            RhinoApp.WriteLine("MeshMachine WIP test", EnglishName);

            Brep SB;

            using (GetObject getBrep = new GetObject())
            {
                getBrep.SetCommandPrompt("Please select the brep to remesh");
                getBrep.Get();
                SB = getBrep.Object(0).Brep();
            }

            //GetNumber TargetLength = new GetNumber();
            //double L = TargetLength.Number();

            Rhino.Input.Custom.GetNumber gn = new Rhino.Input.Custom.GetNumber();
            gn.SetCommandPrompt("Specify a Target Edge Length");
            gn.SetLowerLimit(0.5, false);
            gn.Get();
            if (gn.CommandResult() != Rhino.Commands.Result.Success)
            {
                return(gn.CommandResult());
            }
            double L = gn.Number();

            //Point3d pt0;
            //using (GetPoint getPointAction = new GetPoint())
            //{
            //    getPointAction.SetCommandPrompt("Please select the start point");
            //    if (getPointAction.Get() != GetResult.Point)
            //    {
            //        RhinoApp.WriteLine("No start point was selected.");
            //        return getPointAction.CommandResult();
            //    }
            //    pt0 = getPointAction.Point();
            //}

            //Point3d pt1;
            //using (GetPoint getPointAction = new GetPoint())
            //{
            //    getPointAction.SetCommandPrompt("Please select the end point");
            //    getPointAction.SetBasePoint(pt0, true);
            //    getPointAction.DynamicDraw +=
            //      (sender, e) => e.Display.DrawLine(pt0, e.CurrentPoint, System.Drawing.Color.DarkRed);
            //    if (getPointAction.Get() != GetResult.Point)
            //    {
            //        RhinoApp.WriteLine("No end point was selected.");
            //        return getPointAction.CommandResult();
            //    }
            //    pt1 = getPointAction.Point();
            //}

            //doc.Objects.AddLine(pt0, pt1);

            PlanktonMesh P = new PlanktonMesh();

            List <int> AnchorV        = new List <int>();
            List <int> FeatureV       = new List <int>();
            List <int> FeatureE       = new List <int>();
            double     FixT           = 0.00001;
            double     LengthTol      = 0.15; //a tolerance for when to split/collapse edges
            double     SmoothStrength = 0.8;  //smoothing strength
            double     PullStrength   = 0.8;  //pull to target mesh strength
            double     CurvDep        = 0;
            int        Flip           = 1;

            MeshingParameters MeshParams = new MeshingParameters();

            MeshParams.MaximumEdgeLength = 3 * L;
            MeshParams.MinimumEdgeLength = L;
            MeshParams.JaggedSeams       = false;
            MeshParams.SimplePlanes      = false;

            Mesh[] BrepMeshes = Mesh.CreateFromBrep(SB, MeshParams);
            Mesh   M          = new Mesh();

            foreach (var mesh in BrepMeshes)
            {
                M.Append(mesh);
            }

            M.Faces.ConvertQuadsToTriangles();
            P = M.ToPlanktonMesh();

            var FC = new List <Curve>();

            foreach (BrepEdge E in SB.Edges)
            {
                if (!E.IsSmoothManifoldEdge(0.01))
                {
                    FC.Add(E.ToNurbsCurve());
                }
            }
            var            Corners = SB.Vertices;
            List <Point3d> FV      = new List <Point3d>();

            foreach (Point Pt in Corners)
            {
                FV.Add(Pt.Location);
            }

            //Mark any vertices or edges lying on features
            for (int i = 0; i < P.Vertices.Count; i++)
            {
                Point3d Pt = P.Vertices[i].ToPoint3d();
                AnchorV.Add(-1);
                for (int j = 0; j < FV.Count; j++)
                {
                    if (Pt.DistanceTo(FV[j]) < FixT)
                    {
                        AnchorV[AnchorV.Count - 1] = j;
                    }
                }

                FeatureV.Add(-1);
                for (int j = 0; j < FC.Count; j++)
                {
                    double param = new double();
                    FC[j].ClosestPoint(Pt, out param);
                    if (Pt.DistanceTo(FC[j].PointAt(param)) < FixT)
                    {
                        FeatureV[FeatureV.Count - 1] = j;
                    }
                }
            }

            int EdgeCount = P.Halfedges.Count / 2;

            for (int i = 0; i < EdgeCount; i++)
            {
                FeatureE.Add(-1);
                int vStart = P.Halfedges[2 * i].StartVertex;
                int vEnd   = P.Halfedges[2 * i + 1].StartVertex;

                Point3d PStart = P.Vertices[vStart].ToPoint3d();
                Point3d PEnd   = P.Vertices[vEnd].ToPoint3d();

                for (int j = 0; j < FC.Count; j++)
                {
                    double paramS = new double();
                    double paramE = new double();
                    Curve  thisFC = FC[j];
                    thisFC.ClosestPoint(PStart, out paramS);
                    thisFC.ClosestPoint(PEnd, out paramE);
                    if ((PStart.DistanceTo(thisFC.PointAt(paramS)) < FixT) &&
                        (PEnd.DistanceTo(thisFC.PointAt(paramE)) < FixT))
                    {
                        FeatureE[FeatureE.Count - 1] = j;
                    }
                }
            }



            for (int iter = 0; iter < 30; iter++)
            {
                EdgeCount = P.Halfedges.Count / 2;
                double[]    EdgeLength = P.Halfedges.GetLengths();
                List <bool> Visited    = new List <bool>();
                Vector3d[]  Normals    = new Vector3d[P.Vertices.Count];

                for (int i = 0; i < P.Vertices.Count; i++)
                {
                    Visited.Add(false);
                    Normals[i] = Util.Normal(P, i);
                }

                double t      = LengthTol;      //a tolerance for when to split/collapse edges
                double smooth = SmoothStrength; //smoothing strength
                double pull   = PullStrength;   //pull to target mesh strength

                //    Split the edges that are too long
                for (int i = 0; i < EdgeCount; i++)
                {
                    if (P.Halfedges[2 * i].IsUnused == false)
                    {
                        int vStart = P.Halfedges[2 * i].StartVertex;
                        int vEnd   = P.Halfedges[2 * i + 1].StartVertex;

                        if ((Visited[vStart] == false) &&
                            (Visited[vEnd] == false))
                        {
                            double  L2  = L;
                            Point3d Mid = Util.MidPt(P, i);

                            //if (CurvDep > 0)
                            //{
                            //    double NormDiff = Vector3d.VectorAngle(Normals[vStart], Normals[vEnd]);
                            //    L2 = Math.Min((1.0 / (3.0 * NormDiff) * L), 5 * L);

                            //    if (CurvDep != 1)
                            //    {
                            //        L2 = L2 * (CurvDep) + L * (1.0 - CurvDep);
                            //    }

                            //}
                            //if (BoundScale != 1.0)
                            //{
                            //    double MinDist = 99954;

                            //    for (int j = 0; j < FC.Count; j++)
                            //    {
                            //        double param = new double();

                            //        FC[j].ClosestPoint(Mid, out param);
                            //        double ThisDist = Mid.DistanceTo(FC[j].PointAt(param));
                            //        if (ThisDist < MinDist)
                            //        { MinDist = ThisDist; }
                            //    }

                            //    if (MinDist < BoundDist)
                            //    {
                            //        L2 = L2 * BoundScale + (MinDist / BoundDist) * (L2 * (1 - BoundScale));
                            //    }
                            //}

                            //if (SizP.Count > 0)
                            //{
                            //    L2 = WeightedCombo(Mid, SizP, SizV, WExp, L2, BGW);
                            //    //  L2 = (WL * (1.0 - BGW)) + (BGW * L2);
                            //}

                            if (EdgeLength[2 * i] > (1 + t) * (4f / 3f) * L2)
                            {
                                int SplitHEdge = P.Halfedges.TriangleSplitEdge(2 * i);
                                if (SplitHEdge != -1)
                                {
                                    int SplitCenter = P.Halfedges[SplitHEdge].StartVertex;
                                    P.Vertices.SetVertex(SplitCenter, Util.MidPt(P, i));

                                    //update the feature information
                                    FeatureE.Add(FeatureE[i]);
                                    FeatureV.Add(FeatureE[i]);
                                    AnchorV.Add(-1);

                                    //2 additional new edges have also been created (or 1 if split was on a boundary)
                                    //mark these as non-features
                                    int CEdgeCount = P.Halfedges.Count / 2;
                                    while (FeatureE.Count < CEdgeCount)
                                    {
                                        FeatureE.Add(-1);
                                    }

                                    Visited.Add(true);
                                    int[] Neighbours = P.Vertices.GetVertexNeighbours(SplitCenter);
                                    foreach (int n in Neighbours)
                                    {
                                        Visited[n] = true;
                                    }
                                }
                            }
                        }
                    }
                }

                //Collapse the edges that are too short
                for (int i = 0; i < EdgeCount; i++)
                {
                    if (P.Halfedges[2 * i].IsUnused == false)
                    {
                        int vStart = P.Halfedges[2 * i].StartVertex;
                        int vEnd   = P.Halfedges[2 * i + 1].StartVertex;
                        if ((Visited[vStart] == false) &&
                            (Visited[vEnd] == false))
                        {
                            if (!(AnchorV[vStart] != -1 && AnchorV[vEnd] != -1)) // if both ends are anchored, don't collapse
                            {
                                int Collapse_option = 0;                         //0 for none, 1 for collapse to midpt, 2 for towards start, 3 for towards end
                                //if neither are anchorV
                                if (AnchorV[vStart] == -1 && AnchorV[vEnd] == -1)
                                {
                                    // if both on same feature (or neither on a feature)
                                    if (FeatureV[vStart] == FeatureV[vEnd])
                                    {
                                        Collapse_option = 1;
                                    }
                                    // if start is on a feature and end isn't
                                    if ((FeatureV[vStart] != -1) && (FeatureV[vEnd] == -1))
                                    {
                                        Collapse_option = 2;
                                    }
                                    // if end is on a feature and start isn't
                                    if ((FeatureV[vStart] == -1) && (FeatureV[vEnd] != -1))
                                    {
                                        Collapse_option = 3;
                                    }
                                }
                                else // so one end must be an anchor
                                {
                                    // if start is an anchor
                                    if (AnchorV[vStart] != -1)
                                    {
                                        // if both are on same feature, or if the end is not a feature
                                        if ((FeatureE[i] != -1) || (FeatureV[vEnd] == -1))
                                        {
                                            Collapse_option = 2;
                                        }
                                    }
                                    // if end is an anchor
                                    if (AnchorV[vEnd] != -1)
                                    {
                                        // if both are on same feature, or if the start is not a feature
                                        if ((FeatureE[i] != -1) || (FeatureV[vStart] == -1))
                                        {
                                            Collapse_option = 3;
                                        }
                                    }
                                }

                                double  L2  = L;
                                Point3d Mid = Util.MidPt(P, i);

                                if (CurvDep > 0)
                                {
                                    double NormDiff = Vector3d.VectorAngle(Normals[vStart], Normals[vEnd]);
                                    L2 = Math.Min((1.0 / (3.0 * NormDiff) * L), 5 * L);

                                    if (CurvDep != 1)
                                    {
                                        L2 = L2 * (CurvDep) + L * (1.0 - CurvDep);
                                    }
                                }

                                //if (BoundScale != 1.0)
                                //{
                                //    double MinDist = 99954;

                                //    for (int j = 0; j < FC.Count; j++)
                                //    {
                                //        double param = new double();

                                //        FC[j].ClosestPoint(Mid, out param);
                                //        double ThisDist = Mid.DistanceTo(FC[j].PointAt(param));
                                //        if (ThisDist < MinDist)
                                //        { MinDist = ThisDist; }
                                //    }

                                //    if (MinDist < BoundDist)
                                //    {
                                //        L2 = L2 * BoundScale + (MinDist / BoundDist) * (L2 * (1 - BoundScale));
                                //    }
                                //}

                                //if (SizP.Count > 0)
                                //{
                                //    L2 = WeightedCombo(Mid, SizP, SizV, WExp, L2, BGW);
                                //    //double WL = WeightedCombo(Mid, SizP, SizV, WExp);
                                //    //L2 = (WL * (1.0 - BGW)) + (BGW * L2);
                                //}

                                if ((Collapse_option != 0) && (EdgeLength[2 * i] < (1 - t) * 4f / 5f * L2))
                                {
                                    int Collapsed   = -1;
                                    int CollapseRtn = -1;
                                    if (Collapse_option == 1)
                                    {
                                        Collapsed = P.Halfedges[2 * i].StartVertex;
                                        P.Vertices.SetVertex(Collapsed, Util.MidPt(P, i));
                                        CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                    }
                                    if (Collapse_option == 2)
                                    {
                                        Collapsed   = P.Halfedges[2 * i].StartVertex;
                                        CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                    }
                                    if (Collapse_option == 3)
                                    {
                                        Collapsed   = P.Halfedges[2 * i + 1].StartVertex;
                                        CollapseRtn = P.Halfedges.CollapseEdge(2 * i + 1);
                                    }
                                    if (CollapseRtn != -1)
                                    {
                                        int[] Neighbours = P.Vertices.GetVertexNeighbours(Collapsed);
                                        foreach (int n in Neighbours)
                                        {
                                            Visited[n] = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                EdgeCount = P.Halfedges.Count / 2;

                if ((Flip == 0) && (PullStrength > 0))
                {
                    //Flip edges to reduce valence error
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (!P.Halfedges[2 * i].IsUnused &&
                            (P.Halfedges[2 * i].AdjacentFace != -1) &&
                            (P.Halfedges[2 * i + 1].AdjacentFace != -1) &&
                            (FeatureE[i] == -1)   // don't flip feature edges
                            )
                        {
                            int Vert1 = P.Halfedges[2 * i].StartVertex;
                            int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                            int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                            int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                            int Valence1 = P.Vertices.GetValence(Vert1);
                            int Valence2 = P.Vertices.GetValence(Vert2);
                            int Valence3 = P.Vertices.GetValence(Vert3);
                            int Valence4 = P.Vertices.GetValence(Vert4);

                            if (P.Vertices.NakedEdgeCount(Vert1) > 0)
                            {
                                Valence1 += 2;
                            }
                            if (P.Vertices.NakedEdgeCount(Vert2) > 0)
                            {
                                Valence2 += 2;
                            }
                            if (P.Vertices.NakedEdgeCount(Vert3) > 0)
                            {
                                Valence3 += 2;
                            }
                            if (P.Vertices.NakedEdgeCount(Vert4) > 0)
                            {
                                Valence4 += 2;
                            }

                            int CurrentError =
                                Math.Abs(Valence1 - 6) +
                                Math.Abs(Valence2 - 6) +
                                Math.Abs(Valence3 - 6) +
                                Math.Abs(Valence4 - 6);
                            int FlippedError =
                                Math.Abs(Valence1 - 7) +
                                Math.Abs(Valence2 - 7) +
                                Math.Abs(Valence3 - 5) +
                                Math.Abs(Valence4 - 5);
                            if (CurrentError > FlippedError)
                            {
                                P.Halfedges.FlipEdge(2 * i);
                            }
                        }
                    }
                }
                else
                {
                    //Flip edges based on angle
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (!P.Halfedges[2 * i].IsUnused &&
                            (P.Halfedges[2 * i].AdjacentFace != -1) &&
                            (P.Halfedges[2 * i + 1].AdjacentFace != -1) &&
                            (FeatureE[i] == -1)  // don't flip feature edges
                            )
                        {
                            int Vert1 = P.Halfedges[2 * i].StartVertex;
                            int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                            int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                            int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                            Point3d P1 = P.Vertices[Vert1].ToPoint3d();
                            Point3d P2 = P.Vertices[Vert2].ToPoint3d();
                            Point3d P3 = P.Vertices[Vert3].ToPoint3d();
                            Point3d P4 = P.Vertices[Vert4].ToPoint3d();

                            double A1 = Vector3d.VectorAngle(new Vector3d(P3 - P1), new Vector3d(P4 - P1))
                                        + Vector3d.VectorAngle(new Vector3d(P4 - P2), new Vector3d(P3 - P2));

                            double A2 = Vector3d.VectorAngle(new Vector3d(P1 - P4), new Vector3d(P2 - P4))
                                        + Vector3d.VectorAngle(new Vector3d(P2 - P3), new Vector3d(P1 - P3));

                            if (A2 > A1)
                            {
                                P.Halfedges.FlipEdge(2 * i);
                            }
                        }
                    }
                }

                //if (Minim)
                //{
                //    Vector3d[] SmoothC = LaplacianSmooth(P, 1, smooth);

                //    for (int i = 0; i < P.Vertices.Count; i++)
                //    {
                //        if (AnchorV[i] == -1) // don't smooth feature vertices
                //        {
                //            P.Vertices.MoveVertex(i, 0.5 * SmoothC[i]);
                //        }
                //    }
                //}

                Vector3d[] Smooth = Util.LaplacianSmooth(P, 0, smooth);

                for (int i = 0; i < P.Vertices.Count; i++)
                {
                    if (AnchorV[i] == -1) // don't smooth feature vertices
                    {
                        // make it tangential only
                        Vector3d VNormal    = Util.Normal(P, i);
                        double   ProjLength = Smooth[i] * VNormal;
                        Smooth[i] = Smooth[i] - (VNormal * ProjLength);

                        P.Vertices.MoveVertex(i, Smooth[i]);

                        if (P.Vertices.NakedEdgeCount(i) != 0)//special smoothing for feature edges
                        {
                            int[]   Neighbours = P.Vertices.GetVertexNeighbours(i);
                            int     ncount     = 0;
                            Point3d Avg        = new Point3d();

                            for (int j = 0; j < Neighbours.Length; j++)
                            {
                                if (P.Vertices.NakedEdgeCount(Neighbours[j]) != 0)
                                {
                                    ncount++;
                                    Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                }
                            }
                            Avg = Avg * (1.0 / ncount);
                            Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                            move = move * smooth;
                            P.Vertices.MoveVertex(i, move);
                        }

                        if (FeatureV[i] != -1)//special smoothing for feature edges
                        {
                            int[]   Neighbours = P.Vertices.GetVertexNeighbours(i);
                            int     ncount     = 0;
                            Point3d Avg        = new Point3d();

                            for (int j = 0; j < Neighbours.Length; j++)
                            {
                                if ((FeatureV[Neighbours[j]] == FeatureV[i]) || (AnchorV[Neighbours[j]] != -1))
                                {
                                    ncount++;
                                    Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                }
                            }
                            Avg = Avg * (1.0 / ncount);
                            Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                            move = move * smooth;
                            P.Vertices.MoveVertex(i, move);
                        }

                        //projecting points onto the target along their normals

                        if (pull > 0)
                        {
                            Point3d  Point  = P.Vertices[i].ToPoint3d();
                            Vector3d normal = Util.Normal(P, i);
                            Ray3d    Ray1   = new Ray3d(Point, normal);
                            Ray3d    Ray2   = new Ray3d(Point, -normal);
                            double   RayPt1 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray1);
                            double   RayPt2 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray2);
                            Point3d  ProjectedPt;

                            if ((RayPt1 < RayPt2) && (RayPt1 > 0) && (RayPt1 < 1.0))
                            {
                                ProjectedPt = Point * (1 - pull) + pull * Ray1.PointAt(RayPt1);
                            }
                            else if ((RayPt2 < RayPt1) && (RayPt2 > 0) && (RayPt2 < 1.0))
                            {
                                ProjectedPt = Point * (1 - pull) + pull * Ray2.PointAt(RayPt2);
                            }
                            else
                            {
                                ProjectedPt = Point * (1 - pull) + pull * M.ClosestPoint(Point);
                            }

                            P.Vertices.SetVertex(i, ProjectedPt);
                        }


                        if (FeatureV[i] != -1) //pull feature vertices onto feature curves
                        {
                            Point3d Point     = P.Vertices[i].ToPoint3d();
                            Curve   CF        = FC[FeatureV[i]];
                            double  param1    = 0.0;
                            Point3d onFeature = new Point3d();
                            CF.ClosestPoint(Point, out param1);
                            onFeature = CF.PointAt(param1);
                            P.Vertices.SetVertex(i, onFeature);
                        }
                    }
                    else
                    {
                        P.Vertices.SetVertex(i, FV[AnchorV[i]]); //pull anchor vertices onto their points
                    }
                }



                AnchorV  = Util.CompactByVertex(P, AnchorV); //compact the fixed points along with the vertices
                FeatureV = Util.CompactByVertex(P, FeatureV);
                FeatureE = Util.CompactByEdge(P, FeatureE);

                P.Compact(); //this cleans the mesh data structure of unused elements
            }


            Mesh MR = P.ToRhinoMesh();

            MR.Unweld(0.4, true);

            doc.Objects.AddMesh(MR);

            doc.Views.Redraw();
            RhinoApp.WriteLine("The {0} command added one mesh to the document.", EnglishName);

            // ---

            return(Result.Success);
        }
        /// <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)
        {
            #region updateInputs
            //if (!cap && this.Params.Input.Count ==7)
            //{
            //    this.Params.Input[5].RemoveAllSources();
            //    this.Params.UnregisterInputParameter(this.Params.Input[5]);
            //    this.Params.Input[6].RemoveAllSources();
            //    this.Params.UnregisterInputParameter(this.Params.Input[6]);

            //    Params.OnParametersChanged();
            //}
            //if (cap && this.Params.Input.Count == 5)
            //{
            //    this.Params.RegisterInputParam(new Param_Colour
            //    {
            //        Name = "MinColor",
            //        NickName = "MinColor",
            //        Description = "MinColor",
            //        Access = GH_ParamAccess.item,
            //        Optional = true
            //    });
            //    this.Params.RegisterInputParam(new Param_Colour
            //    {
            //        Name = "MaxColor",
            //        NickName = "MaxColor",
            //        Description = "MinColor",
            //        Access = GH_ParamAccess.item,
            //        Optional = true
            //    });

            //    Params.OnParametersChanged();
            //}

            #endregion updateInputs

            //bool caps = DA.Fetch<bool>("Cap");
            var maxColor   = DA.Fetch <Color>(inputSelecterMax);
            var minColor   = DA.Fetch <Color>(inputSelectorMin);
            var allResults = DA.FetchTree <GH_Number>("Results");
            var grids      = DA.FetchList <Grid>("Grids");
            var range      = DA.Fetch <string>("Range");
            var inStepSize = DA.Fetch <int>("StepSize");
            var inSteps    = DA.Fetch <int>("Steps");

            if (allResults.Branches.Count != grids.Count)
            {
                throw new Exception("Grid count doesnt match results");
            }

            if (!caps)
            {
                this.Params.Input[inputSelectorMin].NickName = "-";
                this.Params.Input[inputSelectorMin].Name     = "-";
                this.Params.Input[inputSelecterMax].NickName = "-";
                this.Params.Input[inputSelecterMax].Name     = "-";
            }
            else
            {
                this.Params.Input[inputSelectorMin].NickName = "MinColor";
                this.Params.Input[inputSelectorMin].Name     = "MinColor";
                this.Params.Input[inputSelecterMax].NickName = "MaxColor";
                this.Params.Input[inputSelecterMax].Name     = "MaxColor";
            }

            var domain = Misc.AutoDomain(range, allResults);
            //Rhino.RhinoApp.WriteLine($"{range}  ->  {domain[0]} to {domain[1]}");

            GH_GradientControl gc;
            try
            {
                gc = (GH_GradientControl)Params.Input[inputGradient].Sources[0].Attributes.GetTopLevel.DocObject;
            }
            catch (System.ArgumentOutOfRangeException)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Remember to add a gradient component in grasshopper!");
                gc = null;
            }

            GradientParser gp = new GradientParser(gc)
            {
                Cap      = caps,
                AboveMax = maxColor,
                BelowMin = minColor,
                Min      = domain[0],
                Max      = domain[1],
                Reverse  = Params.Input[inputGradient].Reverse
            };


            //Rhino.RhinoApp.WriteLine($"Probing {domain[0]} to the value of {gp.GetColors(new List<double> { domain[0] })[0]}");
            //Rhino.RhinoApp.WriteLine($"Probing {domain[1]} to the value of {gp.GetColors(new List<double> { domain[1] })[0]}");

            #region coloredMesh
            var outMeshes = new List <Mesh>();



            for (int i = 0; i < grids.Count; i++)
            {
                //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"Mesh vertices: {grids[i].SimMesh.Vertices.Count}, colors = {gp.GetColors(allResults.Branches[i].Select(p => p.Value).ToArray()).Length} f");


                outMeshes.Add(grids[i].GetColoredMesh(gp.GetColors(allResults.Branches[i].Select(p => p.Value).ToArray())));

                Mesh      m      = grids[i].SimMesh;
                Point3d[] points = grids[i].SimPoints.ToArray();
                outMeshes[outMeshes.Count - 1].Translate(0, 0, Units.ConvertFromMeter(0.001));
            }


            DA.SetDataList(0, outMeshes);

            #endregion coloredMesh



            #region layeredMesh

            if (grids[0].UseCenters == true)
            {
                return;
            }

            //Outputs
            GH_Structure <GH_Mesh>  layeredMeshes = new GH_Structure <GH_Mesh>();
            List <GH_Mesh>          tempMeshes    = new List <GH_Mesh>();
            List <GH_Plane>         outPlanes     = new List <GH_Plane>();
            GH_Structure <GH_Curve> outCurves     = new GH_Structure <GH_Curve>();

            const double SCALAR = 1; // don't change.
            const float  OFFSET = 0.0001f;

            double allMin = double.MaxValue;
            double allMax = -double.MaxValue;

            for (int i = 0; i < allResults.Branches.Count; i++)
            {
                //System.Collections.IList results = allResults.get_Branch(i);

                for (int j = 0; j < allResults[i].Count; j++)
                {
                    double result = allResults[i][j].Value;
                    if (result < allMin)
                    {
                        allMin = result;
                    }
                    if (result > allMax)
                    {
                        allMax = result;
                    }
                }
            }

            stepSize = inStepSize;
            double roundToNearest = 1;
            if (inStepSize == 0) // auto
            {
                //double digits = Math.Round(Math.Log10((domain[1] - domain[0]))) + 1;
                //double multiplier = Math.Pow(10, digits);
                //stepSize = Math.Log10((domain[1] - domain[0]));
                //if (allMax > 1000)
                //    stepSize = 100;
                //else if (allMax > 100)
                //    stepSize = 10;
                //else if (allMax > 10)
                //    stepSize = 1;
                //else
                //    stepSize = 0.1;
                stepSize = Misc.AutoStep(domain, out roundToNearest); // <-- TODO: We can set each slice in exactly the "round to nearest" number.
            }
            else if (inStepSize < 0)                                  // fragment
            {
                stepSize = 1 / Math.Abs(inStepSize);
            }

            steps = Convert.ToInt32((domain[1] - domain[0]) / stepSize);


            for (int g = 0; g < grids.Count; g++)
            {
                //GH_Structure<GH_Curve> curves = new GH_Structure<GH_Curve>();
                Grid grid      = grids[g];
                Mesh meshToCut = grids[g].SimMesh.DuplicateMesh();
                //Mesh meshToCut = grids[g].SimMesh;

                List <double> results = ((List <GH_Number>)allResults.get_Branch(g)).Select(r => r.Value).ToList();

                if (grids[g].UseCenters == true)
                {
                    results = RTreeSolver.FindClosestWeightedValues(grids[g], results, true).ToList();
                    // ADD CONVERSION TODO:
                }



                //Rhino.RhinoApp.WriteLine($"min = {allMin}, max = {allMax}, steps = {steps}, stepsize = {stepSize}");

                if (steps <= 1 || steps > 100)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"too {(steps < 4 ? "few" : "many")} steps (should be between 1 to 100)");
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"min = {allMin}, max = {allMax}, steps = {steps}, stepsize = {stepSize}");
                    continue;
                }

                if (allMax == allMin)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"max==min");
                    continue;
                }
                meshToCut.Normals.ComputeNormals();

                Plane cuttingPlane = new Plane(meshToCut.Vertices[0], meshToCut.FaceNormals[0]);

                //var planeOut = new Plane(plane);

                var planeBottom = new Plane(cuttingPlane);

                //List<int> belongsToWhichLayer = new List<int>();

                Vector3f normal = (Vector3f)(cuttingPlane.ZAxis);
                //AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"normal  x = {normal.X}, Y = {normal.Y}, Z = {normal.Z}");

                planeBottom.Transform(Transform.Translation(-cuttingPlane.ZAxis));

                //Moving the bottom down
                meshToCut.Translate(-normal * OFFSET);

                //Moving the vertices up
                for (int i = 0; i < results.Count; i++)
                {
                    meshToCut.Vertices[i] += (normal) * (float)SCALAR * (OFFSET + (float)results[i]);
                }

                Mesh topMesh = meshToCut.DuplicateMesh();

                tempMeshes.Add(new GH_Mesh(topMesh));

                Mesh edgeMesh = new Mesh();

                List <Point3d> ptOut = new List <Point3d>();
                Polyline[]     edges = meshToCut.GetNakedEdges();

                double totalLength = 0;

                for (int i = 0; i < edges.Length; i++)
                {
                    totalLength += edges[i].Length;
                }

                Polyline[] edgesProjected = new Polyline[edges.Length];

                Transform p = Transform.PlanarProjection(planeBottom);

                for (int i = 0; i < edges.Length; i++)
                {
                    for (int j = 0; j < edges[i].SegmentCount; j++)
                    {
                        Mesh      msh = new Mesh();
                        Point3d[] pts = new Point3d[4];

                        int id = (j == edges[i].SegmentCount - 1) ? 0 : j + 1;

                        pts[0] = new Point3d(edges[i].X[j], edges[i].Y[j], edges[i].Z[j]);
                        pts[1] = new Point3d(edges[i].X[id], edges[i].Y[id], edges[i].Z[id]);
                        pts[2] = new Point3d(pts[1]);
                        pts[3] = new Point3d(pts[0]);
                        pts[2].Transform(p);
                        pts[3].Transform(p);

                        msh.Vertices.AddVertices(pts);
                        var fc = new MeshFace(3, 2, 1, 0);
                        ptOut.AddRange(pts);
                        msh.Faces.AddFace(fc);

                        edgeMesh.Append(msh);
                    }
                }

                meshToCut.Append(edgeMesh);
                meshToCut.Weld(Math.PI);

                tempMeshes.Add(new GH_Mesh(meshToCut));

                //Transform t = Transform.Translation(new Vector3d(0, 0, inStepSize * SCALAR));

                Vector3f v = normal * (float)(stepSize.RoundTo(roundToNearest) * SCALAR);

                Transform t = Transform.Translation(v);

                //AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Vector v = {v.X}, {v.Y}, {v.Z},   instep = ");

                Mesh meshPerArea     = new Mesh();
                MeshingParameters mp = new MeshingParameters(0);


                //double resultValue = inputMin;
                //stepSize = (inputMax - inputMin) / (float)steps;



                double currentValue = domain[0];
                int    cuttingCount = -1;

                while (currentValue <= domain[1])
                {
                    cuttingCount++;

                    if (cuttingCount == 0)
                    {
                        currentValue = domain[0];
                    }


                    if (cuttingCount == 1)
                    {
                        cuttingPlane.Translate(new Vector3d(0, 0, domain[0].RoundTo(roundToNearest)));
                        //currentValue = domain[0];
                    }

                    if (cuttingCount > 0)
                    {
                        currentValue += stepSize;
                    }



                    if (cuttingCount > 80)
                    {
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "ERROR CUT THE CUTTINGCOUNT");
                        break;
                    }

                    //Rhino.RhinoApp.WriteLine($"CurrentValue = {currentValue}, cuttingCount = {cuttingCount}");


                    //var resultValue = (double)cuttingCount / steps * (allMax - allMin) + allMin;


                    //resultValue = (double)cuttingCount / steps * (domain[1] - domain[0]) + domain[0];
                    //resultValue = (double)cuttingCount / steps * (domain[1] - domain[0]) + domain[0];

                    //var resultValue = currentValue; // new

                    //Rhino.RhinoApp.WriteLine($"Cutting {cuttingCount}, {resultValue}, {currentValue}, {allMin} - {allMax}");
                    //if (resultValue < domain[0])
                    //    continue;
                    //if (resultValue > domain[1])
                    //    break;



                    Polyline[] pl = Rhino.Geometry.Intersect.Intersection.MeshPlane(meshToCut, cuttingPlane);
                    outPlanes.Add(new GH_Plane(cuttingPlane));

                    if (pl == null)
                    {
                        break;
                    }



                    Color col = gp.GetColors(new List <double>()
                    {
                        cuttingCount == 0 ? double.MinValue : currentValue.RoundTo(roundToNearest)
                    })[0];
                    //Rhino.RhinoApp.WriteLine($"Probing value {currentValue} to {col}");

                    //Mesh meshPerCut = new Mesh();

                    GH_Path path = new GH_Path(g, cuttingCount);

                    if (pl.Length > 0)
                    {
                        List <Curve> curves = new List <Curve>();
                        for (int j = 0; j < pl.Length; j++)
                        {
                            Curve curve = new PolylineCurve(pl[j]);

                            if (cuttingCount <= 0)
                            {
                                curve.Translate(normal * (float)(domain[0] - stepSize));
                            }


                            curve.Translate(-normal * (float)(currentValue * 0.95 - stepSize)); // was 0.95 nice

                            //curve.Translate(-normal * (float)allMin + normal * (float)(cuttingCount * Units.ConvertFromMeter(0.01)));



                            curves.Add(curve);                           // to create brep later

                            outCurves.Append(new GH_Curve(curve), path); // for output
                        }

                        Brep[] breps2 = Brep.CreatePlanarBreps(curves, Units.ConvertFromMeter(0.001));
                        for (int j = 0; j < breps2.Length; j++)
                        {
                            Mesh[] mesh2 = Mesh.CreateFromBrep(breps2[j], mp);

                            for (int k = 0; k < mesh2.Length; k++)
                            {
                                mesh2[k].VertexColors.CreateMonotoneMesh(col);

                                //meshPerCut.Append(mesh2[k]);

                                layeredMeshes.Append(new GH_Mesh(mesh2[k]), path);
                            }
                        }
                    }

                    //meshPerCut.VertexColors.CreateMonotoneMesh(col);



                    if (cuttingCount > 0)
                    {
                        cuttingPlane.Transform(t);
                    }
                }

                //layeredMeshes.Append(new GH_Mesh(meshPerArea), new GH_Path(g, );
            }



            //for (int j = 0; j < pl.Length; j++)
            //{
            //    Curve curve = pl[j].ToNurbsCurve();
            //    GH_Path path = new GH_Path(g, cuttingCount);

            //    outCurves.Append(new GH_Curve(curve), path);


            //    Brep[] breps = Brep.CreatePlanarBreps(curve, Units.ConvertFromMeter(0.001));

            //    if (breps == null)
            //        continue;

            //    Brep brep = breps[0];

            //    var area = AreaMassProperties.Compute(brep);
            //    if (area.Area > maxSize)
            //    {
            //        maxSize = area.Area;
            //        outerIndex = j;
            //    }
            //}

            //boundaryEdge = pl[outerIndex];


            //for (int j = 0; j < pl.Length; j++)
            //{
            //    if (j != outerIndex)
            //        holes.Add(pl[j].ToNurbsCurve());
            //}

            //Mesh mesh = null;
            //if (boundaryEdge.IsClosed)
            //{
            //    mesh = Mesh.CreatePatch(boundaryEdge, Math.PI / 2.0, null, holes, null, null, false, 0);

            //}
            //else
            //{

            //    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"Curve is not closed");
            //}



            //outPlanes.Add(new GH_Plane(new Plane(cuttingPlane)));



            //int curvesCount = pl.Length;
            //int[] pointsRanges = new int[curvesCount];
            //Point3d[][] pts = new Point3d[curvesCount][];

            //for (int j = 0; j < pl.Length; j++)
            //{
            //    //Mesh mesh = GreenScenario.MeshUtil.CreateMeshWithHoles(pl);
            //    //Mesh mesh = Mesh.CreateFromTessellation(points, pl, Plane.WorldXY, false);
            //    //var mesh = Mesh.CreateFromClosedPolyline(pl[j]);


            //    if (mesh == null)
            //        continue;

            //    //outCurves.Append(new GH_Curve(pl[j].ToNurbsCurve()));

            //    //List<Color> colorList = new List<Color>();

            //    ////for (int i = 0; i < mesh.Faces.Count; i++)
            //    ////{
            //    ////    colorList.Add(col);
            //    ////    colorList.Add(col);
            //    ////    colorList.Add(col);
            //    ////    if (mesh.Faces[i].IsQuad)
            //    ////        colorList.Add(col);
            //    ////}

            //    //for (int i = 0; i < mesh.Vertices.Count; i++)
            //    //{
            //    //    colorList.Add(col);
            //    //}



            //    ////mesh.VertexColors.SetColors(colorList.ToArray());
            //    //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"Vertices = {mesh.Vertices.Count}, colors = {mesh.VertexColors.Count}");

            //    //    mesh.VertexColors.CreateMonotoneMesh(col);
            //    //mesh.Translate(-normal * inStepSize * (float)SCALAR * cuttingCount * 0.90f);

            //    //   meshPerArea.Append(mesh);


            //    // we don't have more heights to cut off.
            //    //if (brep == null)
            //    //    continue;


            //    //for (int i = 0; i < brep.Length; i++)
            //    //{

            //    //    belongsToWhichLayer.Add(count);

            //    //}
            //    //pts.Add(polylinecrv.PointAtStart);


            //}



            // By now curves are moved to different elevations.
            //crvs = crvs;



            //Rhino.RhinoApp.WriteLine("adding a mesh");



            //oNumbers = outNumbers;



            //B = breps;
            //meshOut = mesh;


            Message = $"Cap = {(this.caps ? "on" : "off")} | Steps = {steps} | Step = {stepSize:0.0}";

            DA.SetDataTree(1, layeredMeshes);
            DA.SetDataTree(2, outCurves);
            DA.SetDataList("Planes", outPlanes);
            DA.SetDataList("TempMeshes", tempMeshes);

            #endregion layeredMesh
        }
Пример #25
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ITargetLength TargetLength = null;
            bool reset = false;
            int Flip = 0;
            List<Curve> FC = new List<Curve>();
            List<Point3d> FV = new List<Point3d>();
            double FixT = 0.01;
            double PullStrength = 0.8;
            double SmoothStrength = 0.8;
            double LengthTol = 0.15;
            bool Minim = false;
            int Iters = 1;

            GH_ObjectWrapper Surf = new GH_ObjectWrapper();
            DA.GetData<GH_ObjectWrapper>(0, ref Surf);

            GH_ObjectWrapper Obj = null;
            DA.GetData<GH_ObjectWrapper>(1, ref Obj);
            TargetLength = Obj.Value as ITargetLength;

            DA.GetDataList<Curve>(2, FC);
            DA.GetDataList<Point3d>(3, FV);
            DA.GetData<int>(4, ref Flip);

            DA.GetData<double>(5, ref PullStrength);

            DA.GetData<int>(6, ref Iters);
            DA.GetData<bool>(7, ref reset);

            if (PullStrength == 0) { Minim = true; }

            if (Surf.Value is GH_Mesh)
            {
                DA.GetData<Mesh>(0, ref M);
                M.Faces.ConvertQuadsToTriangles();
            }
            else
            {
                double L = 1.0;
                MeshingParameters MeshParams = new MeshingParameters();
                MeshParams.MaximumEdgeLength = 3 * L;
                MeshParams.MinimumEdgeLength = L;
                MeshParams.JaggedSeams = false;
                MeshParams.SimplePlanes = false;
                Brep SB = null;
                DA.GetData<Brep>(0, ref SB);
                Mesh[] BrepMeshes = Mesh.CreateFromBrep(SB, MeshParams);
                M = new Mesh();
                foreach (var mesh in BrepMeshes)
                    M.Append(mesh);
            }

            if (reset || initialized == false)
            {
                #region reset
                M.Faces.ConvertQuadsToTriangles();
                P = M.ToPlanktonMesh();

                initialized = true;

                AnchorV.Clear();
                FeatureV.Clear();
                FeatureE.Clear();

                //Mark any vertices or edges lying on features
                for (int i = 0; i < P.Vertices.Count; i++)
                {
                    Point3d Pt = P.Vertices[i].ToPoint3d();
                    AnchorV.Add(-1);
                    for (int j = 0; j < FV.Count; j++)
                    {
                        if (Pt.DistanceTo(FV[j]) < FixT)
                        { AnchorV[AnchorV.Count - 1] = j; }
                    }

                    FeatureV.Add(-1);
                    for (int j = 0; j < FC.Count; j++)
                    {
                        double param = new double();
                        FC[j].ClosestPoint(Pt, out param);
                        if (Pt.DistanceTo(FC[j].PointAt(param)) < FixT)
                        { FeatureV[FeatureV.Count - 1] = j; }
                    }
                }

                int EdgeCount = P.Halfedges.Count / 2;
                for (int i = 0; i < EdgeCount; i++)
                {
                    FeatureE.Add(-1);
                    int vStart = P.Halfedges[2 * i].StartVertex;
                    int vEnd = P.Halfedges[2 * i + 1].StartVertex;

                    Point3d PStart = P.Vertices[vStart].ToPoint3d();
                    Point3d PEnd = P.Vertices[vEnd].ToPoint3d();

                    for (int j = 0; j < FC.Count; j++)
                    {
                        double paramS = new double();
                        double paramE = new double();
                        Curve thisFC = FC[j];
                        thisFC.ClosestPoint(PStart, out paramS);
                        thisFC.ClosestPoint(PEnd, out paramE);
                        if ((PStart.DistanceTo(thisFC.PointAt(paramS)) < FixT) &&
                          (PEnd.DistanceTo(thisFC.PointAt(paramE)) < FixT))
                        {
                            FeatureE[FeatureE.Count - 1] = j;
                        }
                    }
                }
                #endregion
            }

            else
            {
                for (int iter = 0; iter < Iters; iter++)
                {
                    int EdgeCount = P.Halfedges.Count / 2;
                    double[] EdgeLength = P.Halfedges.GetLengths();
                    List<bool> Visited = new List<bool>();
                    Vector3d[] Normals = new Vector3d[P.Vertices.Count];

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        Visited.Add(false);
                        Normals[i] = Normal(P, i);
                    }

                    double t = LengthTol;     //a tolerance for when to split/collapse edges
                    double smooth = SmoothStrength;  //smoothing strength
                    double pull = PullStrength;  //pull to target mesh strength

                    // Split the edges that are too long
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd = P.Halfedges[2 * i + 1].StartVertex;

                            if ((Visited[vStart] == false)
                              && (Visited[vEnd] == false))
                            {

                                double L2 = TargetLength.Calculate(P, 2 * i);

                                if (EdgeLength[2 * i] > (1 + t) * (4f / 3f) * L2)
                                {

                                    int SplitHEdge = P.Halfedges.TriangleSplitEdge(2 * i);
                                    if (SplitHEdge != -1)
                                    {
                                        int SplitCenter = P.Halfedges[SplitHEdge].StartVertex;
                                        P.Vertices.SetVertex(SplitCenter, MidPt(P, i));

                                        //update the feature information
                                        FeatureE.Add(FeatureE[i]);
                                        FeatureV.Add(FeatureE[i]);
                                        AnchorV.Add(-1);

                                        //2 additional new edges have also been created (or 1 if split was on a boundary)
                                        //mark these as non-features
                                        int CEdgeCount = P.Halfedges.Count / 2;
                                        while (FeatureE.Count < CEdgeCount)
                                        { FeatureE.Add(-1); }

                                        Visited.Add(true);
                                        int[] Neighbours = P.Vertices.GetVertexNeighbours(SplitCenter);
                                        foreach (int n in Neighbours)
                                        { Visited[n] = true; }
                                    }
                                }

                            }
                        }
                    }

                    //Collapse the edges that are too short
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd = P.Halfedges[2 * i + 1].StartVertex;
                            if ((Visited[vStart] == false)
                              && (Visited[vEnd] == false))
                            {
                                if (!(AnchorV[vStart] != -1 && AnchorV[vEnd] != -1)) // if both ends are anchored, don't collapse
                                {
                                    int Collapse_option = 0; //0 for none, 1 for collapse to midpt, 2 for towards start, 3 for towards end
                                    //if neither are anchorV
                                    if (AnchorV[vStart] == -1 && AnchorV[vEnd] == -1)
                                    {
                                        // if both on same feature (or neither on a feature)
                                        if (FeatureV[vStart] == FeatureV[vEnd])
                                        { Collapse_option = 1; }
                                        // if start is on a feature and end isn't
                                        if ((FeatureV[vStart] != -1) && (FeatureV[vEnd] == -1))
                                        { Collapse_option = 2; }
                                        // if end is on a feature and start isn't
                                        if ((FeatureV[vStart] == -1) && (FeatureV[vEnd] != -1))
                                        { Collapse_option = 3; }
                                    }
                                    else // so one end must be an anchor
                                    {
                                        // if start is an anchor
                                        if (AnchorV[vStart] != -1)
                                        {
                                            // if both are on same feature, or if the end is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vEnd] == -1))
                                            { Collapse_option = 2; }
                                        }
                                        // if end is an anchor
                                        if (AnchorV[vEnd] != -1)
                                        {
                                            // if both are on same feature, or if the start is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vStart] == -1))
                                            { Collapse_option = 3; }
                                        }
                                    }

                                    Point3d Mid = MidPt(P, i);

                                    double L2 = TargetLength.Calculate(P, 2 * i);

                                    if ((Collapse_option != 0) && (EdgeLength[2 * i] < (1 - t) * 4f / 5f * L2))
                                    {
                                        int Collapsed = -1;
                                        int CollapseRtn = -1;
                                        if (Collapse_option == 1)
                                        {
                                            Collapsed = P.Halfedges[2 * i].StartVertex;
                                            P.Vertices.SetVertex(Collapsed, MidPt(P, i));
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 2)
                                        {
                                            Collapsed = P.Halfedges[2 * i].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 3)
                                        {
                                            Collapsed = P.Halfedges[2 * i + 1].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i + 1);
                                        }
                                        if (CollapseRtn != -1)
                                        {
                                            int[] Neighbours = P.Vertices.GetVertexNeighbours(Collapsed);
                                            foreach (int n in Neighbours)
                                            { Visited[n] = true; }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    EdgeCount = P.Halfedges.Count / 2;

                    if ((Flip == 0) && (PullStrength > 0))
                    {
                        //Flip edges to reduce valence error
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused
                              && (P.Halfedges[2 * i].AdjacentFace != -1)
                              && (P.Halfedges[2 * i + 1].AdjacentFace != -1)
                              && (FeatureE[i] == -1)  // don't flip feature edges
                              )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                int Valence1 = P.Vertices.GetValence(Vert1);
                                int Valence2 = P.Vertices.GetValence(Vert2);
                                int Valence3 = P.Vertices.GetValence(Vert3);
                                int Valence4 = P.Vertices.GetValence(Vert4);

                                if (P.Vertices.NakedEdgeCount(Vert1) > 0) { Valence1 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert2) > 0) { Valence2 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert3) > 0) { Valence3 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert4) > 0) { Valence4 += 2; }

                                int CurrentError =
                                  Math.Abs(Valence1 - 6) +
                                  Math.Abs(Valence2 - 6) +
                                  Math.Abs(Valence3 - 6) +
                                  Math.Abs(Valence4 - 6);
                                int FlippedError =
                                  Math.Abs(Valence1 - 7) +
                                  Math.Abs(Valence2 - 7) +
                                  Math.Abs(Valence3 - 5) +
                                  Math.Abs(Valence4 - 5);
                                if (CurrentError > FlippedError)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }
                    else
                    {
                        //Flip edges based on angle
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused
                              && (P.Halfedges[2 * i].AdjacentFace != -1)
                              && (P.Halfedges[2 * i + 1].AdjacentFace != -1)
                              && (FeatureE[i] == -1) // don't flip feature edges
                              )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                Point3d P1 = P.Vertices[Vert1].ToPoint3d();
                                Point3d P2 = P.Vertices[Vert2].ToPoint3d();
                                Point3d P3 = P.Vertices[Vert3].ToPoint3d();
                                Point3d P4 = P.Vertices[Vert4].ToPoint3d();

                                double A1 = Vector3d.VectorAngle(new Vector3d(P3 - P1), new Vector3d(P4 - P1))
                                  + Vector3d.VectorAngle(new Vector3d(P4 - P2), new Vector3d(P3 - P2));

                                double A2 = Vector3d.VectorAngle(new Vector3d(P1 - P4), new Vector3d(P2 - P4))
                                  + Vector3d.VectorAngle(new Vector3d(P2 - P3), new Vector3d(P1 - P3));

                                if (A2 > A1)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }

                    if (Minim)
                    {
                        Vector3d[] SmoothC = LaplacianSmooth(P, 1, smooth);

                        for (int i = 0; i < P.Vertices.Count; i++)
                        {
                            if (AnchorV[i] == -1) // don't smooth feature vertices
                            {
                                P.Vertices.MoveVertex(i, 0.5 * SmoothC[i]);
                            }
                        }
                    }

                    Vector3d[] Smooth = LaplacianSmooth(P, 0, smooth);

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        if (AnchorV[i] == -1) // don't smooth feature vertices
                        {
                            // make it tangential only
                            Vector3d VNormal = Normal(P, i);
                            double ProjLength = Smooth[i] * VNormal;
                            Smooth[i] = Smooth[i] - (VNormal * ProjLength);

                            P.Vertices.MoveVertex(i, Smooth[i]);

                            if (P.Vertices.NakedEdgeCount(i) != 0)//special smoothing for feature edges
                            {
                                int[] Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int ncount = 0;
                                Point3d Avg = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if (P.Vertices.NakedEdgeCount(Neighbours[j]) != 0)
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            if (FeatureV[i] != -1)//special smoothing for feature edges
                            {
                                int[] Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int ncount = 0;
                                Point3d Avg = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if ((FeatureV[Neighbours[j]] == FeatureV[i]) || (AnchorV[Neighbours[j]] != -1))
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            //projecting points onto the target along their normals

                            if (pull > 0)
                            {
                                Point3d Point = P.Vertices[i].ToPoint3d();
                                Vector3d normal = Normal(P, i);
                                Ray3d Ray1 = new Ray3d(Point, normal);
                                Ray3d Ray2 = new Ray3d(Point, -normal);
                                double RayPt1 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray1);
                                double RayPt2 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray2);
                                Point3d ProjectedPt;

                                if ((RayPt1 < RayPt2) && (RayPt1 > 0) && (RayPt1 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray1.PointAt(RayPt1);
                                }
                                else if ((RayPt2 < RayPt1) && (RayPt2 > 0) && (RayPt2 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray2.PointAt(RayPt2);
                                }
                                else
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * M.ClosestPoint(Point);
                                }

                                P.Vertices.SetVertex(i, ProjectedPt);
                            }

                            if (FeatureV[i] != -1) //pull feature vertices onto feature curves
                            {
                                Point3d Point = P.Vertices[i].ToPoint3d();
                                Curve CF = FC[FeatureV[i]];
                                double param1 = 0.0;
                                Point3d onFeature = new Point3d();
                                CF.ClosestPoint(Point, out param1);
                                onFeature = CF.PointAt(param1);
                                P.Vertices.SetVertex(i, onFeature);
                            }
                        }
                        else
                        {
                            P.Vertices.SetVertex(i, FV[AnchorV[i]]); //pull anchor vertices onto their points
                        }
                    }

                    //end new

                    AnchorV = CompactByVertex(P, AnchorV); //compact the fixed points along with the vertices
                    FeatureV = CompactByVertex(P, FeatureV);
                    FeatureE = CompactByEdge(P, FeatureE);

                    P.Compact(); //this cleans the mesh data structure of unused elements
                }

            }

            DA.SetData(0, P);
        }
            public SurfaceSource(IEnumerable<Brep> Surfaces, List<String> CodeList, int el_m, int SrcID, Phase_Regime ph)
                :base(new double[8]{0, 0, 0, 0, 0, 0, 0, 0}, new Point3d(0,0,0), ph, SrcID)
            {
                samplespermeter = el_m;
                
                Srfs = Surfaces.ToList<Brep>();
                Samples = new Point3d[Srfs.Count][];
                
                MeshingParameters mp = new MeshingParameters();
                mp.MaximumEdgeLength = 1.0 / (double)samplespermeter;
                mp.MinimumEdgeLength = 1.0 / (double)samplespermeter;

                Sub_A = new double[Srfs.Count];
                SubDomains = new double[Srfs.Count][];
                T = new Topology[Srfs.Count];

                //for(int i = 0; i < Curves.Count; i++)
                System.Threading.Tasks.Parallel.For(0, Srfs.Count, ips =>
                {
                    int i = (int)ips;
                    
                    
                    //Divide each curve up in ~equal length segments.
                    Mesh[] m = Mesh.CreateFromBrep(Srfs[i],mp);
                    BoundingBox Box = m[0].GetBoundingBox(true);
                    for (int j = 1; j < m.Length; j++) Box.Union(m[j].GetBoundingBox(true));
                    T[i] = new Topology(Utilities.PachTools.RPttoHPt(Box.Min), Utilities.PachTools.RPttoHPt(Box.Max));
                    
                    List<Point3d> pts = new List<Point3d>();
                    SubDomains[i] = new double[m[i].Faces.Count + 1];
                    for (int j = 0; j < m[i].Faces.Count; j++)
                    {
                        double u,v;
                        ComponentIndex ci;
                        Point3d no;
                        Vector3d V;
                        Point3d A = m[i].Vertices[m[i].Faces[j].A];
                        Srfs[i].ClosestPoint(A, out no, out ci, out u, out v, 1, out V);
                        A += V;
                        Point3d B = m[i].Vertices[m[i].Faces[j].B];
                        Srfs[i].ClosestPoint(B, out no, out ci, out u, out v, 1, out V);
                        B += V;
                        Point3d C = m[i].Vertices[m[i].Faces[j].C];
                        Srfs[i].ClosestPoint(C, out no, out ci, out u, out v, 1, out V);
                        C += V;
                        Point3d D = m[i].Vertices[m[i].Faces[j].D];
                        Srfs[i].ClosestPoint(D, out no, out ci, out u, out v, 1, out V);
                        D += V;
                        
                        if (m[i].Faces[j].IsQuad)
                        {
                            Hare.Geometry.Point[] poly = new Hare.Geometry.Point[4];
                            poly[0] = new Hare.Geometry.Point(A.X, A.Y, A.Z);
                            poly[1] = new Hare.Geometry.Point(B.X, B.Y, B.Z);
                            poly[2] = new Hare.Geometry.Point(C.X, C.Y, C.Z);
                            poly[3] = new Hare.Geometry.Point(D.X, D.Y, D.Z);
                            T[i].Add_Polygon(poly);
                        }
                        else
                        {
                            Hare.Geometry.Point[] poly = new Hare.Geometry.Point[3];
                            poly[0] = new Hare.Geometry.Point(A.X, A.Y, A.Z);
                            poly[1] = new Hare.Geometry.Point(B.X, B.Y, B.Z);
                            poly[2] = new Hare.Geometry.Point(C.X, C.Y, C.Z);
                            T[i].Add_Polygon(poly);
                        }

                        pts.Add(m[i].Faces[j].IsQuad ? new Point3d(A.X + B.X + C.X + D.X, A.Y + B.Y + C.Y + D.Y, A.Z + B.Z + C.Z + D.Z) / 4 : new Point3d(A.X + B.X + C.X, A.Y + B.Y + C.Y, A.Z + B.Z + C.Z) / 3);

                        SubDomains[i][j + 1] = Sub_A[i] += T[i].Polygon_Area(j);
                    }
                    Samples[i] = pts.ToArray();
                });

                Domains = new double[Srfs.Count+1];
                DomainLevel = new double[Srfs.Count][];
                DomainPower = new double[Srfs.Count][];
                Total_A = 0;
                
                for (int i = 0; i < Srfs.Count; i++)
                {
                    for (int j = 0; j < SubDomains[i].Length; j++) SubDomains[i][j] /= Sub_A[i];
                    double A = Srfs[i].GetArea();
                    Domains[i + 1] = Total_A += A;
                    DomainLevel[i] = Utilities.PachTools.DecodeSourcePower(CodeList[i]);
                    DomainPower[i] = new double[8];
                    double PowerMod = A;
                    for (int oct = 0; oct < 8; oct++) DomainPower[i][oct] = 1E-12 * Math.Pow(10, .1 * DomainLevel[i][oct]) / PowerMod;
                }

                for (int i = 0; i < Domains.Length; i++)
                {
                    Domains[i] /= Total_A;
                }
            }
Пример #27
0
        /// <summary>
        /// Searches for locations where the distance from a RhinoObject, in one set of objects,
        /// is less than the specified distance to another RhinoObject in a second set of objects.
        /// This function uses the object's mesh to calculate the interferences.
        /// Acceptable object types include: BrepObject, ExtrusionObject, MeshObject, and SubDObject.
        /// </summary>
        /// <param name="setA">The first set of Rhino objects.</param>
        /// <param name="setB">The second set of Rhino objects.</param>
        /// <param name="distance">The largest distance at which a clash can occur.</param>
        /// <param name="meshType">The type of mesh to be used for the calculation.</param>
        /// <param name="meshingParameters">The meshing parameters used to generate meshes for the calculation.</param>
        /// <returns>An array of mesh interference object if successful, or an empty array on failure.</returns>
        public static MeshInterference[] Search(IEnumerable <RhinoObject> setA, IEnumerable <RhinoObject> setB, double distance, MeshType meshType, MeshingParameters meshingParameters)
        {
            using (var set_a_array = new Runtime.InternalRhinoObjectArray(setA))
                using (var set_b_array = new Runtime.InternalRhinoObjectArray(setB))
                {
                    var ptr_set_a        = set_a_array.NonConstPointer();
                    var ptr_set_b        = set_b_array.NonConstPointer();
                    var ptr_mp           = meshingParameters.ConstPointer();
                    var ptr_clash_events = UnsafeNativeMethods.RhObjectClashEventArray_New(); // new
                    var count            = UnsafeNativeMethods.RHC_CRhClashDetect_TestClash(ptr_set_a, ptr_set_b, distance, (int)meshType, ptr_mp, ptr_clash_events);

                    var rc = new MeshInterference[count];
                    for (var i = 0; i < count; i++)
                    {
                        var index_a        = -1;
                        var index_b        = -1;
                        var hit_points     = new SimpleArrayPoint3d(); // new
                        var ptr_hit_points = hit_points.NonConstPointer();
                        var mi             = new MeshInterference();
                        if (UnsafeNativeMethods.RhObjectClashEventArray_GetAt(ptr_clash_events, i, ref index_a, ref index_b, ptr_hit_points))
                        {
                            mi.IndexA    = index_a;
                            mi.IndexB    = index_b;
                            mi.HitPoints = hit_points.Count > 0 ? hit_points.ToArray() : new Point3d[0];
                        }
                        else
                        {
                            mi.IndexA    = -1;
                            mi.IndexB    = -1;
                            mi.HitPoints = new Point3d[0];
                        }
                        hit_points.Dispose(); // delete
                        rc[i] = mi;
                    }

                    UnsafeNativeMethods.RhObjectClashEventArray_Delete(ptr_clash_events); // delete
                    GC.KeepAlive(setA);
                    GC.KeepAlive(setB);
                    return(rc);
                }
        }
Пример #28
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ETABS2013.cOAPI     activate = null;
            List <GeometryBase> surfaces = new List <GeometryBase>();

            if (!DA.GetData(0, ref activate))
            {
                return;
            }
            if (!DA.GetDataList(1, surfaces))
            {
                return;
            }


            /*   for (int i = 0; i < meshes.Count(); i++)
             * {
             *
             *
             *
             *    //Get the contour polyline and its points (this is done to get the points in the right order
             *    Rhino.Geometry.Plane mshPlane = new Rhino.Geometry.Plane(Plane.WorldXY.Origin, new Vector3d(0, 0, 1));
             *    Polyline[] mshOutlines = meshes[i].GetOutlines(mshPlane);
             *    List<Point3d> pts = mshOutlines[0].GetRange(0, mshOutlines[0].Count - 1).ToList(); // Last value in the range is the first point again
             *
             *    //I uset arrays cus the AddByCoord function can only handle arrays
             *    double[] xValues = new double[pts.Count];
             *    double[] yValues = new double[pts.Count];
             *    double[] zValues = new double[pts.Count];
             *    for(int j = 0; j < pts.Count; j++)
             *    {
             *        xValues[j] =pts[j].X;
             *        yValues[j] = pts[j].Y;
             *        zValues[j] = pts[j].Z;
             *    }
             *
             *
             *
             *    string Name = "Slab" + i;
             *    ETABS.SapModel.AreaObj.AddByCoord(pts.Count(), ref xValues, ref yValues, ref zValues, ref Name);
             *    ETABS.SapModel.View.RefreshView(0, false);
             * } */


            //Connect from the input ETABS file
            ETABS2013.cOAPI ETABS = (ETABS2013.cOAPI)activate;
            Mesh            mesh  = new Mesh();

            for (int i = 0; i < surfaces.Count(); i++)
            {
                //If input is brep convert to mesh (easiest way to get the points)
                if (surfaces[i].GetType() == typeof(Rhino.Geometry.Brep))
                {
                    MeshingParameters mshParam = new MeshingParameters();
                    mshParam.MinimumTolerance = 0.01; //we can get meshing params from a standard GH component as it is a generic type

                    Mesh[] mshArray = Mesh.CreateFromBrep((Brep)surfaces[i], mshParam);
                    mesh = mshArray[0];
                }
                //If input is a mesh no convertion is needed
                else if (surfaces[i].GetType() == typeof(Rhino.Geometry.Mesh))
                {
                    mesh = (Mesh)surfaces[i];
                }
                //If not mesh or brep do nothing (return)
                else
                {
                    return;
                }

                //Get the contour polyline and its points (this is done to get the points in the right order
                BoundingBox          bMesh       = new BoundingBox();
                Rhino.Geometry.Plane mshPlane    = new Rhino.Geometry.Plane(bMesh.Center, mesh.FaceNormals[0]);   //Just take one normal on the surface since it's planar
                Polyline[]           mshOutlines = mesh.GetOutlines(mshPlane);
                List <Point3d>       pts         = mshOutlines[0].GetRange(0, mshOutlines[0].Count - 1).ToList(); // Last value in the range is the first point again

                //I use arrays because the AddByCoord function can only handle arrays
                double[] xValues = new double[pts.Count];
                double[] yValues = new double[pts.Count];
                double[] zValues = new double[pts.Count];
                for (int j = 0; j < pts.Count; j++)
                {
                    //Add all the x,y,z values from the mesh into arrays, used in AddByCoord function
                    xValues[j] = pts[j].X;
                    yValues[j] = pts[j].Y;
                    zValues[j] = pts[j].Z;
                }
                string Name = "Slab" + i;
                //Add the mesh in ETABS and refresh the view
                ETABS.SapModel.AreaObj.AddByCoord(pts.Count(), ref xValues, ref yValues, ref zValues, ref Name);
                ETABS.SapModel.View.RefreshView(0, false);



                DA.SetData(0, ETABS);
            }
        }
 /// <summary>
 /// Shorthand tool for map mesh objects.
 /// </summary>
 /// <param name="Map_Srf">A NURBS surface to mesh.</param>
 /// <param name="Increment">the maximum dimension between vertices.</param>
 /// <returns>the map mesh object.</returns>
 public static Mesh Create_Map_Mesh(IEnumerable<Brep> Map_Srf, double Increment)
 {
     Mesh Map_Mesh = new Mesh();
     MeshingParameters mp = new MeshingParameters();
     mp.MaximumEdgeLength = Increment;
     mp.MinimumEdgeLength = Increment;
     mp.SimplePlanes = false;
     mp.JaggedSeams = false;
     Brep[] Srfs = Map_Srf.ToArray<Brep>();
     for (int i = 0; i < Map_Srf.ToArray<Brep>().Length; i++) Map_Mesh.Append(Rhino.Geometry.Mesh.CreateFromBrep(Srfs[i], mp)[0]);
     return Map_Mesh;
 }
Пример #30
0
        /// <summary>
        /// Finds all of the mesh faces on each of two Rhino objects that interfere within a clash distance.
        /// This function uses the object's mesh to calculate the interferences.
        /// Acceptable object types include: BrepObject, ExtrusionObject, MeshObject, and SubDObject.
        /// </summary>
        /// <param name="objA">The first Rhino object.</param>
        /// <param name="objB">The second Rhino object.</param>
        /// <param name="distance">The largest distance at which a clash can occur.</param>
        /// <param name="meshType">The type of mesh to be used for the calculation.</param>
        /// <param name="meshingParameters">The meshing parameters used to generate meshes for the calculation.</param>
        /// <returns>The resulting meshes are sub-meshes of the input meshes if successful, or an empty array on error.</returns>
        public static Mesh[] FindDetail(RhinoObject objA, RhinoObject objB, double distance, MeshType meshType, MeshingParameters meshingParameters)
        {
            if (null == objA)
            {
                throw new ArgumentNullException(nameof(objA));
            }
            if (null == objB)
            {
                throw new ArgumentNullException(nameof(objB));
            }

            using (var out_meshes = new SimpleArrayMeshPointer())
            {
                var ptr_obj_a      = objA.ConstPointer();
                var ptr_obj_b      = objB.ConstPointer();
                var ptr_mp         = meshingParameters.ConstPointer();
                var ptr_out_meshes = out_meshes.NonConstPointer();
                var count          = UnsafeNativeMethods.RHC_CRhClashDetect_FindClashDetail(ptr_obj_a, ptr_obj_b, distance, (int)meshType, ptr_mp, ptr_out_meshes);
                GC.KeepAlive(objA);
                GC.KeepAlive(objB);
                return(count > 0 ? out_meshes.ToNonConstArray() : new Mesh[0]);
            }
        }
Пример #31
0
        /// <summary>
        /// input a List/IGH_GeometricGoo/
        /// List/IGH_GeometricGoo/ shapes = new List/IGH_GeometricGoo/();
        /// DA.GetDataList/IGH_GeometricGoo/(2, shapes);
        /// </summary>
        /// <param name="geometricGoos">List IGH_GeometricGoo  shapes, can be Brep and Mesh</param>
        /// <returns>joinedMesh</returns>
        ///
        public static Mesh ParseToJoinedMesh(List <IGH_GeometricGoo> geometricGoos, out BoundingBox boundingBox, bool parallel = true)
        {
            boundingBox = new BoundingBox();

            if (geometricGoos.Count == 0)
            {
                return(null);
            }

            Mesh[] meshes = new Mesh[geometricGoos.Count];

            Mesh joinedMesh = new Mesh();

            if (parallel)
            {
                Parallel.For(0, geometricGoos.Count, delegate(int i)
                {
                    IGH_GeometricGoo shape = geometricGoos[i];

                    if (shape is Mesh || shape is GH_Mesh)
                    {
                        var geobase = GH_Convert.ToGeometryBase(shape);
                        meshes[i]   = geobase as Mesh;
                    }
                    else if (shape is Brep || shape is GH_Brep)
                    {
                        var geobase          = GH_Convert.ToGeometryBase(shape);
                        Brep brep            = geobase as Brep;
                        MeshingParameters mp = MeshingParameters.Default;

                        Mesh[] meshParts = Mesh.CreateFromBrep(brep, mp);

                        meshes[i] = meshParts[0];

                        for (int j = 1; j < meshParts.Length; j++)
                        {
                            meshes[i].Append(meshParts[j]);
                        }
                    }
                });
            }
            else
            {
                for (int i = 0; i < geometricGoos.Count; i++)
                {
                    IGH_GeometricGoo shape = geometricGoos[i];

                    if (shape is Mesh || shape is GH_Mesh)
                    {
                        var geobase = GH_Convert.ToGeometryBase(shape);
                        meshes[i] = geobase as Mesh;
                    }
                    else if (shape is Brep || shape is GH_Brep)
                    {
                        var  geobase         = GH_Convert.ToGeometryBase(shape);
                        Brep brep            = geobase as Brep;
                        MeshingParameters mp = MeshingParameters.Default;

                        Mesh[] meshParts = Mesh.CreateFromBrep(brep, mp);

                        meshes[i] = meshParts[0];

                        for (int j = 1; j < meshParts.Length; j++)
                        {
                            meshes[i].Append(meshParts[j]);
                        }
                    }
                }
            }

            foreach (var mesh in meshes)
            {
                if (mesh != null)
                {
                    joinedMesh.Append(mesh);
                }
            }


            CleanMesh(joinedMesh);
            boundingBox = joinedMesh.GetBoundingBox(true);

            return(joinedMesh);
        }
Пример #32
0
        internal static IEnumerable <Mesh> GetPreviewMeshes
        (
            this IEnumerable <DB.GeometryObject> geometries,
            MeshingParameters meshingParameters
        )
        {
            var scaleFactor = Revit.ModelUnits;

            foreach (var geometry in geometries)
            {
                if (geometry.Visibility != DB.Visibility.Visible)
                {
                    continue;
                }

                switch (geometry)
                {
                case DB.GeometryInstance instance:
                {
                    var xform = instance.Transform.ToRhino().ChangeUnits(scaleFactor);
                    foreach (var g in instance.SymbolGeometry.GetPreviewMeshes(meshingParameters))
                    {
                        g?.Transform(xform);
                        yield return(g);
                    }
                    break;
                }

                case DB.Mesh mesh:
                {
                    if (mesh.NumTriangles <= 0)
                    {
                        continue;
                    }

                    var m = mesh.ToRhino();

                    yield return(m?.ChangeUnits(scaleFactor));

                    break;
                }

                case DB.Face face:
                {
                    var faceMesh = (meshingParameters is null ? face.Triangulate() : face.Triangulate(meshingParameters.RelativeTolerance));
                    var f        = faceMesh?.ToRhino();

                    yield return(f?.ChangeUnits(scaleFactor));;
                    break;
                }

                case DB.Solid solid:
                {
                    if (solid.Faces.IsEmpty)
                    {
                        continue;
                    }

                    var  solidFaces           = solid.Faces.OfType <DB.Face>();
                    bool useMultipleMaterials = solidFaces.HasMultipleMaterials();
                    var  facesMeshes          = useMultipleMaterials ? null : new List <Mesh>(solid.Faces.Size);
                    foreach (var face in solidFaces)
                    {
                        var faceMesh = (meshingParameters is null ? face.Triangulate() : face.Triangulate(meshingParameters.RelativeTolerance));
                        var f        = faceMesh?.ToRhino().ChangeUnits(scaleFactor);

                        if (facesMeshes is null)
                        {
                            yield return(f);
                        }
                        else if (f is object)
                        {
                            facesMeshes.Add(f);
                        }
                    }

                    if (facesMeshes is object)
                    {
                        if (facesMeshes.Count > 0)
                        {
                            var mesh = new Mesh();

                            mesh.Append(facesMeshes);
                            yield return(mesh);
                        }
                        else
                        {
                            yield return(null);
                        }
                    }
                    break;
                }
                }
            }
        }
            private void Construct(List<Rhino.DocObjects.RhinoObject> ObjectList)
            {
                BoundingBox Box = ObjectList[0].Geometry.GetBoundingBox(true);
                for (int i = 1; i < ObjectList.Count; i++) Box.Union(ObjectList[i].Geometry.GetBoundingBox(true));

                List<GeometryBase> BList = new List<GeometryBase>();

                Brep_ids = new List<int>();

                List<Material> Mat_Layer = new List<Material>();
                List<Scattering> Scat_Layer = new List<Scattering>();
                List<Material> Mat_Obj = new List<Material>();
                List<Scattering> Scat_Obj = new List<Scattering>();
                List<double[]> Trans_Layer = new List<double[]>();
                List<double[]> Trans_Obj = new List<double[]>();
                List<bool> Finite_Layers = new List<bool>();
                List<bool> Finite_Obj = new List<bool>();
                //Organize the geometry into Breps
                //Get materials for each layer:
                for (int l = 0; l < Rhino.RhinoDoc.ActiveDoc.Layers.Count; l++)
                {
                    Rhino.DocObjects.Layer Layer = Rhino.RhinoDoc.ActiveDoc.Layers[l];
                    string abstype = Layer.GetUserString("ABSType");
                    if (abstype == "Buildup")
                    {
                        Finite_Layers.Add(false);
                        string BU = Layer.GetUserString("BuildUp");
                        string[] BU_split = BU.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                        List<AbsorptionModels.ABS_Layer> Buildup = new List<AbsorptionModels.ABS_Layer>();
                        foreach (string swatch in BU_split) Buildup.Add(AbsorptionModels.ABS_Layer.LayerFromCode(swatch));
                        Mat_Layer.Add(new Environment.Smart_Material(Buildup, 44100, Env_Prop.Rho(0), Env_Prop.Sound_Speed(0), 2));

                        double[] Abs = new double[8], Scat = new double[8], Trans = new double[8];
                        Pachyderm_Acoustic.UI.PachydermAc_PlugIn.DecodeAcoustics(Layer.GetUserString("Acoustics"), ref Abs, ref Scat, ref Trans);
                        ///Other properties are still coefficient based...
                        Scat_Layer.Add(new Environment.Lambert_Scattering(Scat, SplitRatio));
                        Trans_Layer.Add(Trans);
                    }
                    else if (abstype == "Buildup_Finite")
                    {
                        Finite_Layers.Add(true);
                        string BU = Layer.GetUserString("BuildUp");
                        string[] BU_split = BU.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                        List<AbsorptionModels.ABS_Layer> Buildup = new List<AbsorptionModels.ABS_Layer>();
                        foreach (string swatch in BU_split) Buildup.Add(AbsorptionModels.ABS_Layer.LayerFromCode(swatch));
                        Environment.Smart_Material sm = new Environment.Smart_Material(Buildup, 44100, Env_Prop.Rho(0), Env_Prop.Sound_Speed(0), 2);
                        Mat_Layer.Add(sm);
                        double[] Abs = new double[8], Scat = new double[8], Trans = new double[8];
                        Pachyderm_Acoustic.UI.PachydermAc_PlugIn.DecodeAcoustics(Layer.GetUserString("Acoustics"), ref Abs, ref Scat, ref Trans);
                        ///Other properties are still coefficient based...
                        Scat_Layer.Add(new Environment.Lambert_Scattering(Scat, SplitRatio));
                        Trans_Layer.Add(Trans);
                    }
                    else
                    {
                        Finite_Layers.Add(false);
                        string spec = Layer.GetUserString("Acoustics");

                        if (spec == "")
                        {
                            ///Layer is not used. As long as there is no geometry for pachyderm on this layer without object set properties, this is ok.
                            Mat_Layer.Add(null);
                            Scat_Layer.Add(null);
                            Trans_Layer.Add(null);
                            continue;
                        }

                        double[] Abs = new double[8], Scat = new double[8], Trans = new double[8];
                        Pachyderm_Acoustic.UI.PachydermAc_PlugIn.DecodeAcoustics(spec, ref Abs, ref Scat, ref Trans);
                        Mat_Layer.Add(new Environment.Basic_Material(Abs, new double[8] { 0, 0, 0, 0, 0, 0, 0, 0 }));
                        Scat_Layer.Add(new Environment.Lambert_Scattering(Scat, SplitRatio));
                        Trans_Layer.Add(Trans);
                    }
                }

                for (int q = 0; q <= ObjectList.Count - 1; q++)
                {
                    List<Brep> B = new List<Brep>();
                    if (ObjectList[q].ObjectType == Rhino.DocObjects.ObjectType.Brep)
                    {
                        Rhino.DocObjects.BrepObject BObj = ((Rhino.DocObjects.BrepObject)ObjectList[q]);
                        B.Add(BObj.BrepGeometry.DuplicateBrep());
                        //string m = ObjectList[q].Geometry.GetUserString("Acoustics_User");
                        if (ObjectList[q].Geometry.GetUserString("Acoustics_User") == "yes")
                        {
                            double[] ABS = new double[8], SCAT = new double[8], TRANS = new double[8];
                            Pachyderm_Acoustic.UI.PachydermAc_PlugIn.DecodeAcoustics(ObjectList[q].Geometry.GetUserString("Acoustics"), ref ABS, ref SCAT, ref TRANS);
                            Mat_Obj.Add(new Basic_Material(ABS, new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }));
                            Finite_Obj.Add(false);
                            Scat_Obj.Add(new Lambert_Scattering(SCAT, SplitRatio));
                            Trans_Obj.Add(TRANS);
                        }
                        else
                        {
                            //Rhino.DocObjects.Layer Layer = Rhino.RhinoDoc.ActiveDoc.Layers[ObjectList[q].Attributes.LayerIndex];
                            //AcousticsData.Add(Layer.GetUserString("Acoustics"));
                            Mat_Obj.Add(Mat_Layer[ObjectList[q].Attributes.LayerIndex]);
                            Scat_Obj.Add(Scat_Layer[ObjectList[q].Attributes.LayerIndex]);
                            Trans_Obj.Add(Trans_Layer[ObjectList[q].Attributes.LayerIndex]);
                            Finite_Obj.Add(Finite_Layers[ObjectList[q].Attributes.LayerIndex]);
                        }
                    }
                    else if (ObjectList[q].ObjectType == Rhino.DocObjects.ObjectType.Extrusion)
                    {
                        Rhino.Geometry.Brep BObj = ((Rhino.DocObjects.ExtrusionObject)ObjectList[q]).ExtrusionGeometry.ToBrep();
                        for (int i = 0; i < BObj.Faces.Count; i++)
                        {
                            if (ObjectList[q].Geometry.GetUserString("Acoustics_User") == "yes")
                            {
                                //AcousticsData.Add(ObjectList[q].Geometry.GetUserString("Acoustics"));
                                double[] ABS = new double[8], SCAT = new double[8], TRANS = new double[8];
                                Pachyderm_Acoustic.UI.PachydermAc_PlugIn.DecodeAcoustics(ObjectList[q].Geometry.GetUserString("Acoustics"), ref ABS, ref SCAT, ref TRANS);
                                Mat_Obj.Add(new Basic_Material(ABS, new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }));
                                Scat_Obj.Add(new Lambert_Scattering(SCAT, SplitRatio));
                                Trans_Obj.Add(TRANS);
                                Finite_Obj.Add(false);
                            }
                            else
                            {
                                //Rhino.DocObjects.Layer Layer = Rhino.RhinoDoc.ActiveDoc.Layers[ObjectList[q].Attributes.LayerIndex];
                                //AcousticsData.Add(Layer.GetUserString("Acoustics"));
                                //Rhino.DocObjects.Layer Layer = Rhino.RhinoDoc.ActiveDoc.Layers[ObjectList[q].Attributes.LayerIndex];
                                //AcousticsData.Add(Layer.GetUserString("Acoustics"));
                                Mat_Obj.Add(Mat_Layer[ObjectList[q].Attributes.LayerIndex]);
                                Scat_Obj.Add(Scat_Layer[ObjectList[q].Attributes.LayerIndex]);
                                Trans_Obj.Add(Trans_Layer[ObjectList[q].Attributes.LayerIndex]);
                                Finite_Obj.Add(Finite_Layers[ObjectList[q].Attributes.LayerIndex]);
                            }

                            //B.Add(BObj.Faces[0].ToBrep());
                            //for (int i = 1; i < BObj.Faces.Count; i++)
                            //{
                            //    if (ObjectList[q].Geometry.GetUserString("Acoustics_User") == "yes")
                            //    {
                            //        AcousticsData.Add(ObjectList[q].Geometry.GetUserString("Acoustics"));
                            //    }
                            //    else
                            //    {
                            //        Rhino.DocObjects.Layer Layer = Rhino.RhinoDoc.ActiveDoc.Layers[ObjectList[q].Attributes.LayerIndex];
                            //        AcousticsData.Add(Layer.GetUserString("Acoustics"));
                            //    }
                            B.Add(BObj.Faces[i].ToBrep());
                        }
                    }
                    else
                    {
                        continue;
                    }
                    BList.AddRange(B);
                }

                ////////////////////////////////////////
                Topo = new Hare.Geometry.Topology[1];
                Topo[0] = new Topology(Utilities.PachTools.RPttoHPt(Box.Min), Utilities.PachTools.RPttoHPt(Box.Max));
                ////////////////////////////////////////
                for (int q = 0; q < BList.Count; q++)
                {
                    for (int r = 0; r < ((Brep)BList[q]).Faces.Count; r++)
                    {
                        BrepList.Add(((Brep)BList[q]).Faces[r].DuplicateFace(false));

                        //Material Abs = null ;
                        //Scattering Scat = null;

                        //double[] Transparency = new double[8];
                        double[] Transmission = new double[8];

                        //double[] Scat = new double[8];
                        //if (!string.IsNullOrEmpty(AcousticsData[q]))
                        //if (Mat_Obj[q] != null)
                        //{
                        //    //double[] Absorption = new double[8];
                        //    //double[] phase = new double[8];
                        //    //double[] Scattering = new double[8];
                        //    ////double[,] Scattering = new double[8, 3];
                        //    //double[] Reflection = new double[8];
                        //    //UI.PachydermAc_PlugIn.DecodeAcoustics(AcousticsData[q], ref Absorption, ref Scattering, ref Transparency);
                        //    Abs = Mat_Obj[q];
                        //    Scat = Scat_Obj[q];
                        //    Transmission = Trans_Obj[q];
                        //}
                        //else
                        if ((Mat_Obj[q] == null) || (Scat_Obj[q] == null) || (Trans_Obj[q] == null))
                        {
                            if (!Custom_Method)
                            {
                                Status = System.Windows.Forms.MessageBox.Show("A material is not specified correctly. Please assign absorption and scattering to all layers in the model.", "Materials Error", System.Windows.Forms.MessageBoxButtons.OK);
                                Complete = false;
                                return;
                            }
                            ///Materials do not need to be specified, as it will not be used for an acoustical simulation... (hopefully...)
                        }

                        //for (int i = 0; i < 8; i++)
                        //{
                        //    Reflection[i] = (1 - Absorption[i]);
                        //    Transmission[i] = Transparency[i];
                        //    Scattering[i, 1] = Scat[i];
                        //    double Mod = ((Scattering[i, 1] < (1 - Scattering[i, 1])) ? (Scattering[i, 1] * SplitRatio / 2) : ((1 - Scattering[i, 1]) * SplitRatio / 2));
                        //    Scattering[i, 0] = Scattering[i, 1] - Mod;
                        //    Scattering[i, 2] = Scattering[i, 1] + Mod;
                        //    phase[i] = 0;
                        //}

                        Mesh[] meshes;
                        MeshingParameters mp = new MeshingParameters();
                        if (Finite_Obj[q])
                        {
                            mp.MinimumEdgeLength = 0.1;
                            mp.SimplePlanes = false;
                        }
                        else
                        {
                            mp.MinimumEdgeLength = 0.1;
                            mp.SimplePlanes = true;
                        }

                        meshes = Rhino.Geometry.Mesh.CreateFromBrep((Brep)BrepList[BrepList.Count - 1], mp);
                        if (meshes == null) throw new Exception("Problem with meshes");

                        for (int t = 0; t < meshes.Length; t++)
                        {
                            if (meshes[t].Faces.Count < 1)
                            {
                                Status = System.Windows.Forms.MessageBox.Show("A surface in the model does not generate a rendermesh. This surface will not be represented in the simulation. It is recommended that you cancel this simulation and repair the affected surface. It can be located in shaded view by finding the surface which generates boundary and isoparm lines, but does not generate a fill. It can sometimes be repaired by running the command 'ShrinkTrimmedSurface'. If this does not work, it will have to be replaced by some means which would generate a proper surface.", "Surface without Rendermesh", System.Windows.Forms.MessageBoxButtons.OKCancel);
                                if (Status == System.Windows.Forms.DialogResult.Cancel)
                                {
                                    Complete = false;
                                    return;
                                }
                                continue;
                            }

                            for (int u = 0; u < meshes[t].Faces.Count; u++)
                            {
                                Hare.Geometry.Point[] P;
                                if (meshes[t].Faces[u].IsQuad)
                                {
                                    P = new Hare.Geometry.Point[4];
                                    Point3f FP = meshes[t].Vertices[meshes[t].Faces[u][0]];
                                    P[0] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                    FP = meshes[t].Vertices[meshes[t].Faces[u][1]];
                                    P[1] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                    FP = meshes[t].Vertices[meshes[t].Faces[u][2]];
                                    P[2] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                    FP = meshes[t].Vertices[meshes[t].Faces[u][3]];
                                    P[3] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                }
                                else
                                {
                                    P = new Hare.Geometry.Point[3];
                                    Point3f FP = meshes[t].Vertices[meshes[t].Faces[u][0]];
                                    P[0] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                    FP = meshes[t].Vertices[meshes[t].Faces[u][1]];
                                    P[1] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                    FP = meshes[t].Vertices[meshes[t].Faces[u][2]];
                                    P[2] = new Hare.Geometry.Point(FP.X, FP.Y, FP.Z);
                                }

                                if (Finite_Obj[q])
                                {
                                    if (!(Mat_Obj[q] is Smart_Material)) throw new Exception("Finite Material must have a Smart_Material...");
                                    Smart_Material mat = Mat_Obj[q] as Smart_Material;
                                    AbsorptionData.Add(new Finite_Material(mat, BrepList[q], meshes[t], u, Env_Prop));
                                }
                                else AbsorptionData.Add(Mat_Obj[q]);
                                ScatteringData.Add(Scat_Obj[q]);
                                TransmissionData.Add(Trans_Obj[q]);

                                bool Trans = false;
                                for (int t_oct = 0; t_oct < 8; t_oct++)
                                {
                                    if (Transmission[t_oct] > 0)
                                    {
                                        Trans = true;
                                        break;
                                    }
                                }
                                Transmissive.Add(Trans);
                                if (BrepList[BrepList.Count - 1].Faces[t].IsPlanar())
                                {
                                    Topo[0].Add_Polygon(P);
                                    Brep_ids.Add(BrepList.Count - 1);
                                }
                                else
                                {
                                    Topo[0].Add_Polygon(new Hare.Geometry.Point[3] { P[0], P[1], P[2] });
                                    Brep_ids.Add(BrepList.Count - 1);
                                    if (P.Length > 3)
                                    {
                                        //break this quad into two polygons in order to avoid warping...
                                        if (Finite_Obj[q])
                                        {
                                            if (!(Mat_Obj[q] is Smart_Material)) throw new Exception("Finite Material must have a Smart_Material...");
                                            Smart_Material mat = Mat_Obj[q] as Smart_Material;
                                            AbsorptionData.Add(new Finite_Material(mat, BrepList[q], meshes[t], u, Env_Prop));
                                        }
                                        else AbsorptionData.Add(Mat_Obj[q]);
                                        ScatteringData.Add(Scat_Obj[q]);
                                        TransmissionData.Add(Trans_Obj[q]);
                                        Transmissive.Add(Trans);
                                        Topo[0].Add_Polygon(new Hare.Geometry.Point[3] { P[0], P[2], P[3] });
                                        Brep_ids.Add(BrepList.Count - 1);
                                    }
                                }
                            }
                        }
                    }
                }

                //Set up a system to find random points on planes.//
                Plane_Area = new double[Topo[0].Plane_Members.Length];
                PolyPlaneFract = new double[Topo[0].Plane_Members.Length][];

                for (int q = 0; q < Topo[0].Plane_Members.Length; q++)
                {
                    foreach (int t in Topo[0].Plane_Members[q])
                    {
                        Plane_Area[q] += Topo[0].Polygon_Area(t);
                    }
                }

                //////////////////////////
                for (int i = 0; i < Topo[0].planeList.Count; i++)
                    for (int j = 0; j < Topo[0].Plane_Members[i].Count; j++)
                    {
                        Point3d pt = Utilities.PachTools.HPttoRPt(Topo[0].Polygon_Centroid(Topo[0].Plane_Members[i][j]));
                        string n = Topo[0].Polys[Topo[0].Plane_Members[i][j]].Plane_ID.ToString();
                    }
                //////////////////////////

                for (int q = 0; q < Topo[0].Plane_Members.Length; q++)
                {
                    PolyPlaneFract[q] = new double[Topo[0].Plane_Members[q].Count];
                    PolyPlaneFract[q][0] = Topo[0].Polygon_Area(Topo[0].Plane_Members[q][0]) / Plane_Area[q];
                    for (int t = 1; t < Topo[0].Plane_Members[q].Count; t++)
                    {
                        PolyPlaneFract[q][t] += PolyPlaneFract[q][t - 1] + Topo[0].Polygon_Area(Topo[0].Plane_Members[q][t]) / Plane_Area[q];
                    }
                }
                Valid = true;

                //Utilities.PachTools.Plot_Hare_Topology(Topo[0]);
            }
Пример #34
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ITargetLength  TargetLength   = null;
            bool           reset          = false;
            int            Flip           = 0;
            List <Curve>   FC             = new List <Curve>();
            List <Point3d> FV             = new List <Point3d>();
            double         FixT           = 0.01;
            double         PullStrength   = 0.8;
            double         SmoothStrength = 0.8;
            double         LengthTol      = 0.15;
            bool           Minim          = false;
            int            Iters          = 1;

            GH_ObjectWrapper Surf = new GH_ObjectWrapper();

            DA.GetData <GH_ObjectWrapper>(0, ref Surf);

            GH_ObjectWrapper Obj = null;

            DA.GetData <GH_ObjectWrapper>(1, ref Obj);
            TargetLength = Obj.Value as ITargetLength;

            DA.GetDataList <Curve>(2, FC);
            DA.GetDataList <Point3d>(3, FV);
            DA.GetData <int>(4, ref Flip);

            DA.GetData <double>(5, ref PullStrength);

            DA.GetData <int>(6, ref Iters);
            DA.GetData <bool>(7, ref reset);


            if (PullStrength == 0)
            {
                Minim = true;
            }

            if (Surf.Value is GH_Mesh)
            {
                DA.GetData <Mesh>(0, ref M);
                M.Faces.ConvertQuadsToTriangles();
            }
            else
            {
                double            L          = 1.0;
                MeshingParameters MeshParams = new MeshingParameters();
                MeshParams.MaximumEdgeLength = 3 * L;
                MeshParams.MinimumEdgeLength = L;
                MeshParams.JaggedSeams       = false;
                MeshParams.SimplePlanes      = false;
                Brep SB = null;
                DA.GetData <Brep>(0, ref SB);
                Mesh[] BrepMeshes = Mesh.CreateFromBrep(SB, MeshParams);
                M = new Mesh();
                foreach (var mesh in BrepMeshes)
                {
                    M.Append(mesh);
                }
            }

            if (reset || initialized == false)
            {
                #region reset
                M.Faces.ConvertQuadsToTriangles();
                P = M.ToPlanktonMesh();

                initialized = true;

                AnchorV.Clear();
                FeatureV.Clear();
                FeatureE.Clear();

                //Mark any vertices or edges lying on features
                for (int i = 0; i < P.Vertices.Count; i++)
                {
                    Point3d Pt = P.Vertices[i].ToPoint3d();
                    AnchorV.Add(-1);
                    for (int j = 0; j < FV.Count; j++)
                    {
                        if (Pt.DistanceTo(FV[j]) < FixT)
                        {
                            AnchorV[AnchorV.Count - 1] = j;
                        }
                    }

                    FeatureV.Add(-1);
                    for (int j = 0; j < FC.Count; j++)
                    {
                        double param = new double();
                        FC[j].ClosestPoint(Pt, out param);
                        if (Pt.DistanceTo(FC[j].PointAt(param)) < FixT)
                        {
                            FeatureV[FeatureV.Count - 1] = j;
                        }
                    }
                }
                //
                int EdgeCount = P.Halfedges.Count / 2;
                for (int i = 0; i < EdgeCount; i++)
                {
                    FeatureE.Add(-1);
                    //同一条线分为两条线编号分别为2i和2i+1,朝向相对,两个的起始点为
                    int vStart = P.Halfedges[2 * i].StartVertex;
                    int vEnd   = P.Halfedges[2 * i + 1].StartVertex;

                    Point3d PStart = P.Vertices[vStart].ToPoint3d();
                    Point3d PEnd   = P.Vertices[vEnd].ToPoint3d();

                    for (int j = 0; j < FC.Count; j++)
                    {
                        double paramS = new double();
                        double paramE = new double();
                        Curve  thisFC = FC[j];
                        thisFC.ClosestPoint(PStart, out paramS);
                        thisFC.ClosestPoint(PEnd, out paramE);
                        if ((PStart.DistanceTo(thisFC.PointAt(paramS)) < FixT) &&
                            (PEnd.DistanceTo(thisFC.PointAt(paramE)) < FixT))
                        {
                            FeatureE[FeatureE.Count - 1] = j;
                        }
                    }
                }
                #endregion
            }

            else
            {
                for (int iter = 0; iter < Iters; iter++)
                {
                    int         EdgeCount  = P.Halfedges.Count / 2;
                    double[]    EdgeLength = P.Halfedges.GetLengths();
                    List <bool> Visited    = new List <bool>();
                    Vector3d[]  Normals    = new Vector3d[P.Vertices.Count];

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        Visited.Add(false);
                        Normals[i] = Normal(P, i);
                    }

                    double t      = LengthTol;      //a tolerance for when to split/collapse edges
                    double smooth = SmoothStrength; //smoothing strength
                    double pull   = PullStrength;   //pull to target mesh strength

                    // Split the edges that are too long
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd   = P.Halfedges[2 * i + 1].StartVertex;

                            if ((Visited[vStart] == false) &&
                                (Visited[vEnd] == false))
                            {
                                double L2 = TargetLength.Calculate(P, 2 * i);

                                if (EdgeLength[2 * i] > (1 + t) * (4f / 3f) * L2)
                                {
                                    int SplitHEdge = P.Halfedges.TriangleSplitEdge(2 * i);
                                    if (SplitHEdge != -1)
                                    {
                                        int SplitCenter = P.Halfedges[SplitHEdge].StartVertex;
                                        P.Vertices.SetVertex(SplitCenter, MidPt(P, i));

                                        //update the feature information
                                        FeatureE.Add(FeatureE[i]);
                                        FeatureV.Add(FeatureE[i]);
                                        AnchorV.Add(-1);

                                        //2 additional new edges have also been created (or 1 if split was on a boundary)
                                        //mark these as non-features
                                        int CEdgeCount = P.Halfedges.Count / 2;
                                        while (FeatureE.Count < CEdgeCount)
                                        {
                                            FeatureE.Add(-1);
                                        }

                                        Visited.Add(true);
                                        int[] Neighbours = P.Vertices.GetVertexNeighbours(SplitCenter);
                                        foreach (int n in Neighbours)
                                        {
                                            Visited[n] = true;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //Collapse the edges that are too short
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd   = P.Halfedges[2 * i + 1].StartVertex;
                            if ((Visited[vStart] == false) &&
                                (Visited[vEnd] == false))
                            {
                                if (!(AnchorV[vStart] != -1 && AnchorV[vEnd] != -1)) // if both ends are anchored, don't collapse
                                {
                                    int Collapse_option = 0;                         //0 for none, 1 for collapse to midpt, 2 for towards start, 3 for towards end
                                    //if neither are anchorV
                                    if (AnchorV[vStart] == -1 && AnchorV[vEnd] == -1)
                                    {
                                        // if both on same feature (or neither on a feature)
                                        if (FeatureV[vStart] == FeatureV[vEnd])
                                        {
                                            Collapse_option = 1;
                                        }
                                        // if start is on a feature and end isn't
                                        if ((FeatureV[vStart] != -1) && (FeatureV[vEnd] == -1))
                                        {
                                            Collapse_option = 2;
                                        }
                                        // if end is on a feature and start isn't
                                        if ((FeatureV[vStart] == -1) && (FeatureV[vEnd] != -1))
                                        {
                                            Collapse_option = 3;
                                        }
                                    }
                                    else // so one end must be an anchor
                                    {
                                        // if start is an anchor
                                        if (AnchorV[vStart] != -1)
                                        {
                                            // if both are on same feature, or if the end is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vEnd] == -1))
                                            {
                                                Collapse_option = 2;
                                            }
                                        }
                                        // if end is an anchor
                                        if (AnchorV[vEnd] != -1)
                                        {
                                            // if both are on same feature, or if the start is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vStart] == -1))
                                            {
                                                Collapse_option = 3;
                                            }
                                        }
                                    }

                                    Point3d Mid = MidPt(P, i);


                                    double L2 = TargetLength.Calculate(P, 2 * i);



                                    if ((Collapse_option != 0) && (EdgeLength[2 * i] < (1 - t) * 4f / 5f * L2))
                                    {
                                        int Collapsed   = -1;
                                        int CollapseRtn = -1;
                                        if (Collapse_option == 1)
                                        {
                                            Collapsed = P.Halfedges[2 * i].StartVertex;
                                            P.Vertices.SetVertex(Collapsed, MidPt(P, i));
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 2)
                                        {
                                            Collapsed   = P.Halfedges[2 * i].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 3)
                                        {
                                            Collapsed   = P.Halfedges[2 * i + 1].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i + 1);
                                        }
                                        if (CollapseRtn != -1)
                                        {
                                            int[] Neighbours = P.Vertices.GetVertexNeighbours(Collapsed);
                                            foreach (int n in Neighbours)
                                            {
                                                Visited[n] = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    EdgeCount = P.Halfedges.Count / 2;

                    if ((Flip == 0) && (PullStrength > 0))
                    {
                        //Flip edges to reduce valence error
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused &&
                                (P.Halfedges[2 * i].AdjacentFace != -1) &&
                                (P.Halfedges[2 * i + 1].AdjacentFace != -1) &&
                                (FeatureE[i] == -1)   // don't flip feature edges
                                )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                int Valence1 = P.Vertices.GetValence(Vert1);
                                int Valence2 = P.Vertices.GetValence(Vert2);
                                int Valence3 = P.Vertices.GetValence(Vert3);
                                int Valence4 = P.Vertices.GetValence(Vert4);

                                if (P.Vertices.NakedEdgeCount(Vert1) > 0)
                                {
                                    Valence1 += 2;
                                }
                                if (P.Vertices.NakedEdgeCount(Vert2) > 0)
                                {
                                    Valence2 += 2;
                                }
                                if (P.Vertices.NakedEdgeCount(Vert3) > 0)
                                {
                                    Valence3 += 2;
                                }
                                if (P.Vertices.NakedEdgeCount(Vert4) > 0)
                                {
                                    Valence4 += 2;
                                }

                                int CurrentError =
                                    Math.Abs(Valence1 - 6) +
                                    Math.Abs(Valence2 - 6) +
                                    Math.Abs(Valence3 - 6) +
                                    Math.Abs(Valence4 - 6);
                                int FlippedError =
                                    Math.Abs(Valence1 - 7) +
                                    Math.Abs(Valence2 - 7) +
                                    Math.Abs(Valence3 - 5) +
                                    Math.Abs(Valence4 - 5);
                                if (CurrentError > FlippedError)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }
                    else
                    {
                        //Flip edges based on angle
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused &&
                                (P.Halfedges[2 * i].AdjacentFace != -1) &&
                                (P.Halfedges[2 * i + 1].AdjacentFace != -1) &&
                                (FeatureE[i] == -1)  // don't flip feature edges
                                )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                Point3d P1 = P.Vertices[Vert1].ToPoint3d();
                                Point3d P2 = P.Vertices[Vert2].ToPoint3d();
                                Point3d P3 = P.Vertices[Vert3].ToPoint3d();
                                Point3d P4 = P.Vertices[Vert4].ToPoint3d();

                                double A1 = Vector3d.VectorAngle(new Vector3d(P3 - P1), new Vector3d(P4 - P1))
                                            + Vector3d.VectorAngle(new Vector3d(P4 - P2), new Vector3d(P3 - P2));

                                double A2 = Vector3d.VectorAngle(new Vector3d(P1 - P4), new Vector3d(P2 - P4))
                                            + Vector3d.VectorAngle(new Vector3d(P2 - P3), new Vector3d(P1 - P3));

                                if (A2 > A1)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }

                    if (Minim)
                    {
                        Vector3d[] SmoothC = LaplacianSmooth(P, 1, smooth);

                        for (int i = 0; i < P.Vertices.Count; i++)
                        {
                            if (AnchorV[i] == -1) // don't smooth feature vertices
                            {
                                P.Vertices.MoveVertex(i, 0.5 * SmoothC[i]);
                            }
                        }
                    }

                    Vector3d[] Smooth = LaplacianSmooth(P, 0, smooth);

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        if (AnchorV[i] == -1) // don't smooth feature vertices
                        {
                            // make it tangential only
                            Vector3d VNormal    = Normal(P, i);
                            double   ProjLength = Smooth[i] * VNormal;
                            Smooth[i] = Smooth[i] - (VNormal * ProjLength);

                            P.Vertices.MoveVertex(i, Smooth[i]);

                            if (P.Vertices.NakedEdgeCount(i) != 0)//special smoothing for feature edges
                            {
                                int[]   Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int     ncount     = 0;
                                Point3d Avg        = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if (P.Vertices.NakedEdgeCount(Neighbours[j]) != 0)
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            if (FeatureV[i] != -1)//special smoothing for feature edges
                            {
                                int[]   Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int     ncount     = 0;
                                Point3d Avg        = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if ((FeatureV[Neighbours[j]] == FeatureV[i]) || (AnchorV[Neighbours[j]] != -1))
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            //projecting points onto the target along their normals

                            if (pull > 0)
                            {
                                Point3d  Point  = P.Vertices[i].ToPoint3d();
                                Vector3d normal = Normal(P, i);
                                Ray3d    Ray1   = new Ray3d(Point, normal);
                                Ray3d    Ray2   = new Ray3d(Point, -normal);
                                double   RayPt1 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray1);
                                double   RayPt2 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray2);
                                Point3d  ProjectedPt;

                                if ((RayPt1 < RayPt2) && (RayPt1 > 0) && (RayPt1 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray1.PointAt(RayPt1);
                                }
                                else if ((RayPt2 < RayPt1) && (RayPt2 > 0) && (RayPt2 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray2.PointAt(RayPt2);
                                }
                                else
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * M.ClosestPoint(Point);
                                }

                                P.Vertices.SetVertex(i, ProjectedPt);
                            }


                            if (FeatureV[i] != -1) //pull feature vertices onto feature curves
                            {
                                Point3d Point     = P.Vertices[i].ToPoint3d();
                                Curve   CF        = FC[FeatureV[i]];
                                double  param1    = 0.0;
                                Point3d onFeature = new Point3d();
                                CF.ClosestPoint(Point, out param1);
                                onFeature = CF.PointAt(param1);
                                P.Vertices.SetVertex(i, onFeature);
                            }
                        }
                        else
                        {
                            P.Vertices.SetVertex(i, FV[AnchorV[i]]); //pull anchor vertices onto their points
                        }
                    }



                    //end new



                    AnchorV  = CompactByVertex(P, AnchorV); //compact the fixed points along with the vertices
                    FeatureV = CompactByVertex(P, FeatureV);
                    FeatureE = CompactByEdge(P, FeatureE);

                    P.Compact(); //this cleans the mesh data structure of unused elements
                }
            }

            DA.SetData(0, P);
        }