public static double[] BestCutY(List <double[, ]> contours, int numCuts, double errorTolerance) { double[] yCuts = new double[numCuts]; double area = 0; double maxY = -1000; double minY = 1000; double error, yCut, newArea; //Get the total area of contours: for (int i = 0; i < contours.Count; i++) { if (contours[i].Length != 0) { area += Geom.Geometry.Area(contours[i]); } } for (int cut = 0; cut < numCuts; cut++) { double areaGoal = (double)(cut + 1) / (numCuts + 1); // fractional area goal for each cut. //Now get the max and min Y for the structure for (int j = 0; j < contours.Count; j++) { if (contours[j].Length != 0) { for (int row = 0; row < contours[j].Length / 3; row++) //get the maximum, minimum y { if (contours[j][row, 1] > maxY) { maxY = contours[j][row, 1]; } if (contours[j][row, 1] < minY) { minY = contours[j][row, 1]; } } } } //Now iteratively get equal volumes to the error allowance set List <double[, ]> tempContours = new List <double[, ]>(); List <double[]> cutContours = new List <double[]>(); //store contour as a list to append easily. do { tempContours.Clear(); yCut = (minY + maxY) / 2; newArea = 0; //First add the intersection points: for (int i = 0; i < contours.Count; i++) { cutContours.Clear(); if (contours[i].Length != 0) { tempContours.Add(AddIntersectionsY(contours[i], yCut)); tempContours[i] = ContourFixing.ClosedLooper(tempContours[i]); //now make a new contour with points below yCut. for (int j = 0; j < tempContours[i].Length / 3; j++) { if (tempContours[i][j, 1] <= yCut) { cutContours.Add(new double[] { tempContours[i][j, 0], tempContours[i][j, 1], tempContours[i][j, 2] }); } } if (cutContours.Count != 0) { cutContours = ContourFixing.ClosedLooper(cutContours); newArea += Geom.Geometry.Area(cutContours); } } } //Now compare areas: if (newArea / area < areaGoal) { minY = yCut; } else if (newArea / area > areaGoal) { maxY = yCut; } error = Math.Abs((newArea / area) - areaGoal); } while (error > errorTolerance); yCuts[cut] = yCut; } return(yCuts); }
public static List <List <double[, ]> > YChop(List <double[, ]> contours, int numCutsY) { double[] yCuts = BestCutY(contours, numCutsY, 0.0001); //Contains y-values for cut locations // add intersection points for (int i = 0; i < contours.Count; i++) { contours[i] = AddIntersectionsY(contours[i], yCuts); contours[i] = ContourFixing.ClosedLooper(contours[i]); } ////////////////////////////////////// //Now divide into separate parts. /////////////////////////////////////// List <List <double[, ]> > finalContours = new List <List <double[, ]> >(); //make a list for each y division for the current contour. List <List <double[]> > divisions = new List <List <double[]> >(); //Make the list the correct size so that there is an item for each y division. for (int div = 0; div <= yCuts.Length; div++) { finalContours.Add(new List <double[, ]>()); } for (int i = 0; i < contours.Count; i++) //for all of the contours { divisions.Clear(); //Make the list the correct size so that there is an item for each y division. for (int div = 0; div <= yCuts.Length; div++) { divisions.Add(new List <double[]>()); } for (int y = 0; y <= yCuts.Length; y++) //a section for every cut, + 1 { for (int j = 0; j < contours[i].Length / 3; j++) //loop through all points { if (y == 0) { if (contours[i][j, 1] <= yCuts[y]) { divisions[y].Add(new double[] { contours[i][j, 0], contours[i][j, 1], contours[i][j, 2] }); } } else if (y == yCuts.Length) { if (contours[i][j, 1] >= yCuts[y - 1]) { divisions[y].Add(new double[] { contours[i][j, 0], contours[i][j, 1], contours[i][j, 2] }); } } else { if ((contours[i][j, 1] >= yCuts[y - 1]) && (contours[i][j, 1] <= yCuts[y])) { divisions[y].Add(new double[] { contours[i][j, 0], contours[i][j, 1], contours[i][j, 2] }); } } } } //at this point divisions has a list item holding a list of array points for each cut. //Need to now make double arrays for each of these and add them to new final list. double[,] temp; for (int y = 0; y <= yCuts.Length; y++) //a section for every cut, + 1 { temp = new double[divisions[y].Count, 3]; for (int row = 0; row < temp.Length / 3; row++) { temp[row, 0] = divisions[y][row][0]; temp[row, 1] = divisions[y][row][1]; temp[row, 2] = divisions[y][row][2]; } if (temp.Length != 0) { temp = ContourFixing.ClosedLooper(temp); finalContours[y].Add(temp); } } } return(finalContours); }