/// <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) { bool run = false; if (!DA.GetData(9, ref run)) { return; } else if (run == false) { return; } //import parameters List <double> traffic = new List <double>(); if (!DA.GetDataList(0, traffic)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No Traffic Data"); return; } if (!DA.GetDataTree(1, out GH_Structure <GH_Brep> sidewalk)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No Sidewalk Data"); return; } double r = 0; double iteration = 0; double pow = 0; double delta = 0; double ftApart = 0; DA.GetData(2, ref r); DA.GetDataTree(3, out GH_Structure <GH_Point> subway); DA.GetDataTree(4, out GH_Structure <GH_Point> intpts); DA.GetData(5, ref pow); DA.GetData(6, ref ftApart); DA.GetData(7, ref delta); DA.GetData(8, ref iteration); GH_Structure <GH_Number> distance = new GH_Structure <GH_Number>(); GH_Structure <GH_Point> attractors = new GH_Structure <GH_Point>(); //flatten all interest points for (int i = 0; i < traffic.Count; i++) { List <GH_Point> tmp = new List <GH_Point>(); if (subway.DataCount != 0) { tmp.AddRange(subway[i]); } if (intpts.DataCount != 0) { tmp.AddRange(intpts[i]); } attractors.AppendRange(tmp, new GH_Path(i)); } List <Point3d[]> vertextmp = new List <Point3d[]>(); //calculate and iterate distance for (int i = 0; i < traffic.Count; i++) { for (int j = 0; j < sidewalk[i].Count; j++) { //create grid points Point3d[] corners = sidewalk[i][j].Value.GetBoundingBox(true).GetCorners(); Point3d mincorner = corners[0]; Point3d maxcorner = corners[2]; double x_length = maxcorner.X - mincorner.X; double y_length = maxcorner.Y - mincorner.Y; int x_count = Convert.ToInt32(Math.Ceiling(x_length / delta)); int y_count = Convert.ToInt32(Math.Ceiling(y_length / delta)); List <Point3d> grid = squaregrid(mincorner, delta, x_count, y_count); Point3d[] projected = Intersection.ProjectPointsToBreps(GHBrepToBrep(sidewalk[i]), grid, new Vector3d(0, 0, 1), 0.01); vertextmp.Add(projected); //iterations for (int k = 0; k < iteration; k++) { Point3dList rndpts = new Point3dList(); List <GH_Number> ptdistances = new List <GH_Number>(); List <Point3d> att = new List <Point3d>(); //check if attractor exist if (attractors[i].Count != 0) { att.AddRange(GHPtToPt(attractors[i])); rndpts = Populate(sidewalk[i][j].Value, traffic[i], k, att, r, pow); } else { att.Add(new Point3d(0, 0, 0)); rndpts = Populate(sidewalk[i][j].Value, traffic[i], k, att, 0.001, 0); } for (int g = 0; g < projected.Length; g++) { Point3dList tmp = rndpts.Duplicate(); double tmpDist = 0; //find 2 cloest points to grid point for (int aa = 0; aa < 2; aa++) { int id1 = tmp.ClosestIndex(projected[g]); Point3d tmppt = tmp[id1]; tmp.RemoveAt(id1); for (int ab = 0; ab < 2; ab++) { Point3dList tmp2 = tmp.Duplicate(); int tmpid = tmp2.ClosestIndex(tmppt); tmpDist += tmppt.DistanceTo(tmp2[tmpid]); tmp2.RemoveAt(tmpid); } } //average tmpDist /= 4; ptdistances.Add(new GH_Number(tmpDist)); } distance.AppendRange(ptdistances, new GH_Path(new int[] { i, j, k })); } } } //collapse dtat tree and calculate average distance at each grid point List <List <double> > avg = new List <List <double> >(); for (int i = 0; i < traffic.Count; i++) { List <double> tmp = new List <double>(); for (int j = 0; j < sidewalk[i].Count; j++) { for (int k = 0; k < iteration; k++) { List <double> tmpNumber = GHNumToDouble(distance.get_Branch(new GH_Path(new int[] { i, j, k })) as List <GH_Number>); if (tmp.Count == 0) { tmp.AddRange(tmpNumber); } else { for (int t = 0; t < tmp.Count; t++) { tmp[t] += tmpNumber[t]; tmp[t] /= 2; } } } } avg.Add(tmp); } //convert double to GH_Number GH_Structure <GH_Number> dist = new GH_Structure <GH_Number>(); List <GH_Number> incidents = new List <GH_Number>(); List <List <int> > colids = new List <List <int> >(); for (int i = 0; i < avg.Count; i++) { dist.AppendRange(DoubleToGHNum(avg[i]), new GH_Path(i)); List <int> collisionindex = new List <int>(); //counts grid points with distance smaller than desired int counter = 0; for (int j = 0; j < avg[i].Count; j++) { if (avg[i][j] < ftApart) { collisionindex.Add(j); counter++; } } colids.Add(collisionindex); incidents.Add(new GH_Number(counter)); } //create mesh and visualize data List <GH_Mesh> problem = new List <GH_Mesh>(); List <GH_Mesh> ghmesh = new List <GH_Mesh>(); for (int i = 0; i < vertextmp.Count; i++) { Mesh pArea = new Mesh(); Mesh sidewalkmesh = new Mesh(); List <double> tmpdist = new List <double>(); tmpdist.AddRange(avg[i]); tmpdist.Sort(); double minD = tmpdist[0]; double maxD = tmpdist[tmpdist.Count - 1]; double range = Math.Max(Math.Abs(minD - ftApart), Math.Abs(maxD - ftApart)); for (int j = 0; j < vertextmp[i].Length; j++) { double colordata = avg[i][j]; double dif = Math.Abs(ftApart - colordata); if (dif > range) { dif = range; } double normalized = dif / range * 255; int red = 0; int green = 255; int blue = 0; Mesh meshtmp = new Mesh(); double startx = vertextmp[i][j].X; double starty = vertextmp[i][j].Y; double startz = vertextmp[i][j].Z; double hd = delta / 2; meshtmp.Vertices.Add(new Point3d(startx - hd, starty - hd, startz)); meshtmp.Vertices.Add(new Point3d(startx + hd, starty - hd, startz)); meshtmp.Vertices.Add(new Point3d(startx + hd, starty + hd, startz)); meshtmp.Vertices.Add(new Point3d(startx - hd, starty + hd, startz)); if (colordata <= ftApart) { red = Convert.ToInt32(Math.Round(normalized)); } else { blue = Convert.ToInt32(Math.Round(normalized)); } meshtmp.VertexColors.Add(red, green, blue); meshtmp.VertexColors.Add(red, green, blue); meshtmp.VertexColors.Add(red, green, blue); meshtmp.VertexColors.Add(red, green, blue); meshtmp.Faces.AddFace(0, 1, 2, 3); sidewalkmesh.Append(meshtmp); for (int k = 0; k < colids[i].Count; k++) { if (j == colids[i][k]) { pArea.Append(meshtmp); } } } problem.Add(new GH_Mesh(pArea)); ghmesh.Add(new GH_Mesh(sidewalkmesh)); } DA.SetDataTree(0, dist); DA.SetDataList(1, ghmesh); DA.SetDataList(2, incidents); DA.SetDataList(3, problem); }