/// <summary> /// Remove points and add intersection points in case of backward order /// </summary> /// <param name="X">x values of curve</param> /// <param name="Y">y values of curve</param> /// <param name="lower">if true, algorithm for lower tube curve is used;<para> /// if false, algorithm for upper tube curve is used</para></param> /// <return>Number of loops, that are removed.</return> private static int removeLoop(List<double> X, List<double> Y, bool lower) { // Visualization of working of removeLoop bool visualize = false; List<double> XLoops = new List<double>(X); List<double> YLoops = new List<double>(Y); int j = 1; int countLoops = 0; #if GUI // Visualization if (visualize) { ChartControl chartControl = new ChartControl(600, Int32.MaxValue, true); chartControl.AddLine("Tube curve with loop", X, Y, Color.FromKnownColor(KnownColor.Cyan)); Application.Run(chartControl); } #endif while (j < X.Count - 2) { // Find backward segment (j, j + 1) if (X[j + 1] < X[j]) { countLoops++; // ---------------------------------------------------------------------------------------------------- // 1. Find i,k, such that i <= j < j + 1 <= k - 1 and segment (i - 1, i) intersect segment (k - 1, k) // ---------------------------------------------------------------------------------------------------- int i, k, iPrevious; double y; // for calculation and adding of intersection point bool addPoint = true; double ix = 0; double iy = 0; i = j; iPrevious = i; // Find initial value for i = i_s, such that X[i_s - 1] <= X[j + 1] < X[i_s] // it holds: i element of interval (i_s, j) while (X[j + 1] < X[i - 1]) // X[j + 1] < X[i - 1] => (i - 1 > 0 && Y[i - 2] <= Y[i - 1]) (in case of lower) i--; // initial value for k k = j + 1; y = Y[i - 1]; // X[i - 1] <= X[j + 1] == X[k] < X[i] && in case of lower: y == Y[i - 1] <= Y[i] <= Y[j] == Y[j + 1] == Y[k] // Find k while (((lower && y < Y[k]) || (!lower && Y[k] < y)) && k + 1 < Y.Count)// y < Y[k] => k < X.Count { iPrevious = i; k++; while (X[i] < X[k] && i < j) i++; // it holds X[i - 1] < X[k] <= X[i], particularly X[i] != X[i - 1] // linear interpolation of (x, y) = (X[k], y) on segment (i - 1, i) y = (Y[i] - Y[i - 1]) / (X[i] - X[i - 1]) * (X[k] - X[i - 1]) + Y[i - 1]; } // k located: intersection point is on segment (k - 1, k) // i approximately located: intersection point is on polygonal line (iPrevoius - 1, i) // Regular case if (iPrevious > 1) i = iPrevious - 1; // Special case handling: assure, that i - 1 >= 0 else i = iPrevious; if (X[k] != X[k - 1]) // linear interpolation of (x, y) = (X[i], y) on segment (k - 1, k) y = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]) * (X[i] - X[k - 1]) + Y[k - 1]; // it holds Y[i] = Y[iPrevious - 1] < Y[k - 1] // Find i while ((X[k] != X[k - 1] && ((lower && Y[i] < y) || (!lower && y < Y[i]))) || (X[k] == X[k - 1] && X[i] < X[k])) { i++; if (X[k] != X[k - 1]) // linear interpolation of (x, y) = (X[i], y) on segment (k - 1, k) y = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]) * (X[i] - X[k - 1]) + Y[k - 1]; } // ---------------------------------------------------------------------------------------------------- // 2. Calculate intersection point (ix, iy) of segments (i - 1, i) and (k - 1, k) // ---------------------------------------------------------------------------------------------------- double a1 = 0; double a2 = 0; // both branches vertical if (X[i] == X[i - 1] && X[k] == X[k - 1]) { // add no point; check if case occur: slopes have different signs addPoint = false; } // case i-branch vertical else if (X[i] == X[i - 1]) { ix = X[i]; iy = Y[k - 1] + ((X[i] - X[k - 1]) * (Y[k] - Y[k - 1])) / (X[k] - X[k - 1]); } // case k-branch vertical else if (X[k] == X[k - 1]) { ix = X[k]; iy = Y[i - 1] + ((X[k] - X[i - 1]) * (Y[i] - Y[i - 1])) / (X[i] - X[i - 1]); } // common case else { a1 = (Y[i] - Y[i - 1]) / (X[i] - X[i - 1]); // slope of segment (i - 1, i) a2 = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]); // slope of segment (k - 1, k) // common case: no equal slopes if (a1 != a2) { ix = (a1 * X[i - 1] - a2 * X[k - 1] - Y[i - 1] + Y[k - 1]) / (a1 - a2); if (Math.Abs(a1) > Math.Abs(a2)) // calculate y on segment (k - 1, k) iy = a2 * (ix - X[k - 1]) + Y[k - 1]; else // calculate y on segment (i - 1, i) iy = a1 * (ix - X[i - 1]) + Y[i - 1]; } else // case equal slopes: add no point addPoint = false; } // ---------------------------------------------------------------------------------------------------- // 3. Delete points i until (including) k - 1 // ---------------------------------------------------------------------------------------------------- int count = k - i; X.RemoveRange(i, count); Y.RemoveRange(i, count); // ---------------------------------------------------------------------------------------------------- // 4. Add intersection point // ---------------------------------------------------------------------------------------------------- // add intersection point, if it isn`t already there if (addPoint && (X[i] != ix || Y[i] != iy)) { X.Insert(i, ix); Y.Insert(i, iy); } // ---------------------------------------------------------------------------------------------------- // 5. set j = i // ---------------------------------------------------------------------------------------------------- j = i; // ---------------------------------------------------------------------------------------------------- // 6. Delete points that are doubled // ---------------------------------------------------------------------------------------------------- if (X[i - 1] == X[i] && Y[i - 1] == Y[i]) { X.RemoveAt(i); Y.RemoveAt(i); j = i - 1; } } j++; } #if GUI // Visualization if (visualize) { ChartControl control = new ChartControl(500, Int32.MaxValue, true); control.AddLine("Tube curve with loop", XLoops, YLoops, Color.FromKnownColor(KnownColor.Cyan)); control.AddLine("Tube curve without loop", X, Y, Color.FromKnownColor(KnownColor.Red)); Application.Run(control); } #endif return countLoops; }
/// <summary> /// Remove points and add intersection points in case of backward order /// </summary> /// <param name="X">x values of curve</param> /// <param name="Y">y values of curve</param> /// <param name="lower">if true, algorithm for lower tube curve is used;<para> /// if false, algorithm for upper tube curve is used</para></param> /// <return>Number of loops, that are removed.</return> private static int removeLoop(List <double> X, List <double> Y, bool lower) { // Visualization of working of removeLoop bool visualize = false; List <double> XLoops = new List <double>(X); List <double> YLoops = new List <double>(Y); int j = 1; int countLoops = 0; #if GUI // Visualization if (visualize) { ChartControl chartControl = new ChartControl(600, Int32.MaxValue, true); chartControl.AddLine("Tube curve with loop", X, Y, Color.FromKnownColor(KnownColor.Cyan)); Application.Run(chartControl); } #endif while (j < X.Count - 2) { // Find backward segment (j, j + 1) if (X[j + 1] < X[j]) { countLoops++; // ---------------------------------------------------------------------------------------------------- // 1. Find i,k, such that i <= j < j + 1 <= k - 1 and segment (i - 1, i) intersect segment (k - 1, k) // ---------------------------------------------------------------------------------------------------- int i, k, iPrevious; double y; // for calculation and adding of intersection point bool addPoint = true; double ix = 0; double iy = 0; int kMax; i = j; iPrevious = i; // Find initial value for i = i_s, such that X[i_s - 1] <= X[j + 1] < X[i_s] // it holds: i element of interval (i_s, j) while (X[j + 1] < X[i - 1]) // X[j + 1] < X[i - 1] => (i - 1 > 0 && Y[i - 2] <= Y[i - 1]) (in case of lower) { i--; } // j + 1 < k <= kMax kMax = j + 1; while (X[kMax] < X[j] && kMax < Y.Count - 1) { kMax++; } // initial value for k k = j + 1; y = Y[i - 1]; // X[i - 1] <= X[j + 1] == X[k] < X[i] && in case of lower: y == Y[i - 1] <= Y[i] <= Y[j] == Y[j + 1] == Y[k] // Find k while (((lower && y < Y[k]) || (!lower && Y[k] < y)) && k < kMax)// y < Y[k] => k < X.Count { iPrevious = i; k++; //while ((X[i] < X[k] || (X[i] == X[k] && Y[i] < Y[k])) && i < j) while ((X[i] < X[k] || (lower && X[i] == X[k] && Y[i] < Y[k] && !(k + 1 < X.Count && X[k] == X[k + 1] && Y[k + 1] < Y[k])) || (!lower && X[i] == X[k] && Y[i] > Y[k] && !(k + 1 < X.Count && X[k] == X[k + 1] && Y[k + 1] > Y[k]))) && i < j) { i++; } // it holds X[i - 1] < X[k] <= X[i], particularly X[i] != X[i - 1] // for i < j and X[i - 1] < X[k] it holds X[i - 1] < X[k] <= X[i], particularly X[i] != X[i - 1] // linear interpolation of (x, y) = (X[k], y) on segment (i - 1, i) if (X[i] - X[i - 1] != 0) { y = (Y[i] - Y[i - 1]) / (X[i] - X[i - 1]) * (X[k] - X[i - 1]) + Y[i - 1]; } else { y = Y[i]; } } // k located: intersection point is on segment (k - 1, k) // i approximately located: intersection point is on polygonal line (iPrevoius - 1, i) // Regular case if (iPrevious > 1) { i = iPrevious - 1; } // Special case handling: assure, that i - 1 >= 0 else { i = iPrevious; } if (X[k] != X[k - 1]) { // linear interpolation of (x, y) = (X[i], y) on segment (k - 1, k) y = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]) * (X[i] - X[k - 1]) + Y[k - 1]; } // it holds Y[i] = Y[iPrevious - 1] < Y[k - 1] // Find i while ((X[k] != X[k - 1] && ((lower && Y[i] < y) || (!lower && y < Y[i]))) || (X[k] == X[k - 1] && X[i] < X[k])) { i++; if (X[k] != X[k - 1]) { // linear interpolation of (x, y) = (X[i], y) on segment (k - 1, k) y = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]) * (X[i] - X[k - 1]) + Y[k - 1]; } } // ---------------------------------------------------------------------------------------------------- // 2. Calculate intersection point (ix, iy) of segments (i - 1, i) and (k - 1, k) // ---------------------------------------------------------------------------------------------------- double a1 = 0; double a2 = 0; // both branches vertical if (X[i] == X[i - 1] && X[k] == X[k - 1]) { // add no point; check if case occur: slopes have different signs addPoint = false; } // case i-branch vertical else if (X[i] == X[i - 1]) { ix = X[i]; iy = Y[k - 1] + ((X[i] - X[k - 1]) * (Y[k] - Y[k - 1])) / (X[k] - X[k - 1]); } // case k-branch vertical else if (X[k] == X[k - 1]) { ix = X[k]; iy = Y[i - 1] + ((X[k] - X[i - 1]) * (Y[i] - Y[i - 1])) / (X[i] - X[i - 1]); } // common case else { a1 = (Y[i] - Y[i - 1]) / (X[i] - X[i - 1]); // slope of segment (i - 1, i) a2 = (Y[k] - Y[k - 1]) / (X[k] - X[k - 1]); // slope of segment (k - 1, k) // common case: no equal slopes if (a1 != a2) { ix = (a1 * X[i - 1] - a2 * X[k - 1] - Y[i - 1] + Y[k - 1]) / (a1 - a2); if (Math.Abs(a1) > Math.Abs(a2)) { // calculate y on segment (k - 1, k) iy = a2 * (ix - X[k - 1]) + Y[k - 1]; } else { // calculate y on segment (i - 1, i) iy = a1 * (ix - X[i - 1]) + Y[i - 1]; } } else { // case equal slopes: add no point addPoint = false; } } // ---------------------------------------------------------------------------------------------------- // 3. Delete points i until (including) k - 1 // ---------------------------------------------------------------------------------------------------- int count = k - i; X.RemoveRange(i, count); Y.RemoveRange(i, count); // ---------------------------------------------------------------------------------------------------- // 4. Add intersection point // ---------------------------------------------------------------------------------------------------- // add intersection point, if it isn`t already there if (addPoint && (X[i] != ix || Y[i] != iy)) { X.Insert(i, ix); Y.Insert(i, iy); } // ---------------------------------------------------------------------------------------------------- // 5. set j = i // ---------------------------------------------------------------------------------------------------- j = i; // ---------------------------------------------------------------------------------------------------- // 6. Delete points that are doubled // ---------------------------------------------------------------------------------------------------- if (X[i - 1] == X[i] && Y[i - 1] == Y[i]) { X.RemoveAt(i); Y.RemoveAt(i); j = i - 1; } } j++; } #if GUI // Visualization if (visualize) { ChartControl control = new ChartControl(500, Int32.MaxValue, true); control.AddLine("Tube curve with loop", XLoops, YLoops, Color.FromKnownColor(KnownColor.Cyan)); control.AddLine("Tube curve without loop", X, Y, Color.FromKnownColor(KnownColor.Red)); Application.Run(control); } #endif return(countLoops); }