/// <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
        }
Exemple #2
0
        public static Dictionary <OSMTag, List <Brep> > BuildingBrepsFromCoords(ref RequestHandler result, bool outputHeighted)
        {
            var   geometryResult  = new Dictionary <OSMTag, List <Brep> >();
            var   unitScale       = RhinoMath.UnitScale(UnitSystem.Meters, RhinoDoc.ActiveDoc.ModelUnitSystem); // OSM conversion assumes meters
            var   tolerance       = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
            Coord lengthPerDegree = GetDegreesPerAxis(result.MinBounds, result.MaxBounds, unitScale);

            foreach (var entry in result.FoundData)
            {
                geometryResult[entry.Key] = new List <Brep>();

                for (int i = entry.Value.Count - 1; i >= 0; i--)
                {
                    var outlinePoints = new List <Point3d>();
                    foreach (var coord in entry.Value[i].Coords)
                    {
                        outlinePoints.Add(GetPointFromLatLong(coord, lengthPerDegree, result.MinBounds));
                    }

                    var outline = new PolylineCurve(outlinePoints); // Creating a polylinecurve from scratch makes invalid geometry
                    if (!outline.IsClosed)
                    {
                        if (outline.IsClosable(ALLOWABLE_CLOSURE)) // Force-close the curve
                        {
                            outline.MakeClosed(ALLOWABLE_CLOSURE);
                        }
                        else // Skip this curve as no valid Brep can be made
                        {
                            entry.Value.RemoveAt(i);
                            continue;
                        }
                    }

                    var height = GetBuildingHeights.ParseHeight(entry.Value[i].Tags, unitScale);
                    if (outputHeighted && height > 0.0) // Output heighted buildings
                    {
                        var toHeight = new Vector3d(0, 0, height);

                        var envelope = Surface.CreateExtrusion(outline, toHeight);
                        var floor    = Brep.CreatePlanarBreps(outline, tolerance);
                        outline.Translate(toHeight);
                        var roof = Brep.CreatePlanarBreps(outline, tolerance);

                        var volume = Brep.JoinBreps(new Brep[] { floor[0], envelope.ToBrep(), roof[0] }, tolerance);
                        geometryResult[entry.Key].Add(volume[0]);
                    }
                    else if (!outputHeighted && height == 0.0) // Output unheighted buildings
                    {
                        var builtSurface = Brep.CreatePlanarBreps(outline, tolerance);
                        if (builtSurface != null && builtSurface.Length > 0)
                        {
                            geometryResult[entry.Key].Add(builtSurface[0]);
                        }
                    }
                    else // Item wasn't matched, so should be removed from result so its metadata is not output
                    {
                        entry.Value.RemoveAt(i);
                    }
                }

                geometryResult[entry.Key].Reverse(); // We iterated in reverse order, so swap list back to right direction
            }

            return(geometryResult);
        }