public void GetMxR(int startInd, int endInd, int channel) { // MxR -> Max Rate // MxR Needs the Vpp points, so we calculate those first // Do Vpp Vector2[] pointsIn = new Vector2[endInd - startInd]; Vector2[] pointsInRem = new Vector2[endInd - startInd]; for (int i = 0; i < endInd - startInd; i++) { pointsIn[i] = workingData[i + startInd, channel]; pointsInRem[i] = workingData[i + startInd, channel]; } // Get points on convex hull using Andrew's monotone chain algorithm int n = pointsIn.Length; int k = 0; int mid; Vector2[] H = new Vector2[2 * n]; //var sortedP = pointsIn.OrderBy(p => p.X).ThenBy(p => p.Y); //pointsIn = sortedP.ToArray(); Vec2Compare comp = new Vec2Compare(); // I think this is faster than the LINQ above Array.Sort(pointsIn, comp); // Lower Hull for (int i = 0; i < n; ++i) { while (k >= 2 && Cross(H[k - 2], H[k - 1], pointsIn[i]) <= 0) { k--; } H[k++] = pointsIn[i]; } mid = k; // Remeber upper from lower hull // Upper Hull for (int i = n - 2, t = k + 1; i >= 0; i--) { while (k >= t && Cross(H[k - 2], H[k - 1], pointsIn[i]) <= 0) { k--; } H[k++] = pointsIn[i]; } if (k > 1) { Vector2[] trimmed = new Vector2[k - 1]; for (int i = 0; i < k - 1; i++) { trimmed[i] = H[i]; } H = trimmed; } convexHull = new int[H.Length]; for (int i = 0; i < H.Length; i++) { convexHull[i] = startInd + Array.IndexOf(pointsInRem, H[i]); } // Brute force the points on the convex hull (for now) // There are O(n) ways of doing this, but it shouldn't matter much Vector2 tempPoint1 = new Vector2(), tempPoint2 = new Vector2(); double biggestDist = -1.0; for (int i = 0; i < H.GetLength(0) - 1; i++) { for (int j = i + 1; j < H.GetLength(0); j++) { double d = DistSquared(H[i], H[j]); if (d > biggestDist) { biggestDist = d; tempPoint1 = H[i]; tempPoint2 = H[j]; } } } measureInd1 = startInd + Array.IndexOf(pointsInRem, tempPoint1); measureInd2 = startInd + Array.IndexOf(pointsInRem, tempPoint2); measureAmplitude = Math.Sqrt(biggestDist); // Vpp points found, and amplitude calculated! // Now we can do the MxR part // MxR angle calculation int index1 = Math.Min(measureInd1, measureInd2) - startInd; int index2 = Math.Max(measureInd1, measureInd2) - startInd; const double TOL = 2.5; // This value taken from ADAPT's MxR algorithm int tail = index1, bestHead = index1 + 1, bestTail = index1; double angle = GetECAngle(pointsInRem[tail], pointsInRem[index1 + 1]); double lastAngle = angle; double bestLength = DistSquared(pointsInRem[tail], pointsInRem[index1 + 1]); for (int i = index1 + 1; i < index2; i++) { angle = GetECAngle(pointsInRem[i], pointsInRem[i + 1]); if (Math.Abs(angle - lastAngle) > TOL) { if (DistSquared(pointsInRem[i], pointsInRem[tail]) > bestLength) { bestTail = tail; bestLength = DistSquared(pointsInRem[i], pointsInRem[tail]); bestHead = i; } tail = i; } lastAngle = angle; } measurementPhase = GetECAngle(pointsInRem[bestTail], pointsInRem[bestHead]); mxRInd1 = bestHead + startInd; mxRInd2 = bestTail + startInd; measurementType = "MxR"; }
public void GetVpp(int startInd, int endInd, int channel) { Vector2[] pointsIn = new Vector2[endInd - startInd]; Vector2[] pointsInRem = new Vector2[endInd - startInd]; for (int i = 0; i < endInd - startInd; i++) { pointsIn[i] = workingData[i + startInd, channel]; pointsInRem[i] = workingData[i + startInd, channel]; } //========== // Fast Vpp //========== // Get points on convex hull using Andrew's monotone chain algorithm int n = pointsIn.Length; int k = 0; int mid; Vector2[] H = new Vector2[2 * n]; //var sortedP = pointsIn.OrderBy(p => p.X).ThenBy(p => p.Y); //pointsIn = sortedP.ToArray(); Vec2Compare comp = new Vec2Compare(); // I think this is faster than the LINQ above Array.Sort(pointsIn, comp); // Lower Hull for (int i = 0; i < n; ++i) { while (k >= 2 && Cross(H[k - 2], H[k - 1], pointsIn[i]) <= 0) { k--; } H[k++] = pointsIn[i]; } mid = k; // Remember upper from lower hull (would be used in rotating caliper's algo.) // Upper Hull for (int i = n - 2, t = k + 1; i >= 0; i--) { while (k >= t && Cross(H[k - 2], H[k - 1], pointsIn[i]) <= 0) { k--; } H[k++] = pointsIn[i]; } if (k > 1) { Vector2[] trimmed = new Vector2[k - 1]; for (int i = 0; i < k - 1; i++) { trimmed[i] = H[i]; } H = trimmed; } convexHull = new int[H.Length]; for (int i = 0; i < H.Length; i++) { convexHull[i] = startInd + Array.IndexOf(pointsInRem, H[i]); } // Brute force the points on the convex hull (for now) // There are O(n) ways of doing this, but it shouldn't matter much Vector2 tempPoint1 = new Vector2(), tempPoint2 = new Vector2(); double biggestDist = -1.0; for (int i = 0; i < H.GetLength(0) - 1; i++) { for (int j = i + 1; j < H.GetLength(0); j++) { double d = DistSquared(H[i], H[j]); if (d > biggestDist) { biggestDist = d; tempPoint1 = H[i]; tempPoint2 = H[j]; } } } //measurePoint1 = tempPoint1; //measurePoint2 = tempPoint2; measureInd1 = startInd + Array.IndexOf(pointsInRem, tempPoint1); measureInd2 = startInd + Array.IndexOf(pointsInRem, tempPoint2); measureAmplitude = Math.Sqrt(biggestDist); if (measureInd1 < measureInd2) { measurementPhase = GetECAngle(tempPoint1, tempPoint2); } else { measurementPhase = GetECAngle(tempPoint2, tempPoint1); } measurementType = "Vpp"; // Find the maximum distance with the rotating calipers algorithm //double longest = 0; //int index1 = -1, index2 = -1; //int bot = 0; //int top = H.Length - 1; // //// First set of points //double ds = DistSquared(H[bot], H[top]); //longest = ds; //index1 = bot; //index2 = top; // //while (bot < mid || top >= mid) //{ // if (bot == mid) // top--; // else if (top == mid + 1) // bot++; // else if ( // (H[bot + 1].Y - H[bot].Y) * (H[top].X - H[top - 1].X) > // (H[bot + 1].X - H[bot].X) * (H[top].Y - H[top - 1].Y)) // bot++; // else // top--; // // ds = DistSquared(H[bot], H[top]); // if (ds > longest) // { // longest = ds; // index1 = bot; // index2 = top; // } //} //measurePoint1 = H[index1]; //measurePoint2 = H[index2]; //return new MeasurementResult { // MeasurementType = "Vpp", // Amplitude = longest //}; }