private float ComputeCalibratedAngle(PointF o, PointF a, PointF b, bool signed, bool ccw, CalibrationHelper calibration)
        {
            if (calibration == null)
            {
                throw new InvalidProgramException();
            }

            PointF o2 = calibration.GetPoint(o);
            PointF a2 = calibration.GetPoint(a);
            PointF b2 = calibration.GetPoint(b);

            float value = 0;

            if (ccw)
            {
                value = GeometryHelper.GetAngle(o2, a2, b2);
            }
            else
            {
                value = GeometryHelper.GetAngle(o2, b2, a2);
            }

            if (!signed && value < 0)
            {
                value = (float)(TAU + value);
            }

            return(value);
        }
Exemple #2
0
        private void ComputeRotationCircle(TrajectoryKinematics kinematics, CalibrationHelper calibrationHelper)
        {
            if (kinematics.Length < 3)
            {
                return;
            }

            // Least-squares circle fitting.
            // Ref: "Circle fitting by linear and nonlinear least squares", Coope, I.D.,
            // Journal of Optimization Theory and Applications Volume 76, Issue 2, New York: Plenum Press, February 1993.
            // Implementation based on JS implementation:
            // http://jsxgraph.uni-bayreuth.de/wiki/index.php/Least-squares_circle_fitting

            int    rows = kinematics.Length;
            Matrix m    = new Matrix(rows, 3);
            Matrix v    = new Matrix(rows, 1);

            for (int i = 0; i < rows; i++)
            {
                PointF point = kinematics.Coordinates(i);
                m[i, 0] = point.X;
                m[i, 1] = point.Y;
                m[i, 2] = 1.0;
                v[i, 0] = point.X * point.X + point.Y * point.Y;
            }

            Matrix mt = m.Clone();

            mt.Transpose();
            Matrix b = mt.Multiply(m);
            Matrix c = mt.Multiply(v);
            Matrix z = b.Solve(c);

            PointF center = new PointF((float)(z[0, 0] * 0.5), (float)(z[1, 0] * 0.5));
            double radius = Math.Sqrt(z[2, 0] + (center.X * center.X) + (center.Y * center.Y));

            kinematics.RotationCenter = center;
            kinematics.RotationRadius = radius;

            for (int i = 0; i < rows; i++)
            {
                PointF xAxis = center.Translate(100.0f, 0.0f);
                float  angle = GeometryHelper.GetAngle(center, xAxis, kinematics.Coordinates(i));
                if (angle < 0)
                {
                    angle = (float)((Math.PI * 2) + angle);
                }

                kinematics.AbsoluteAngle[i] = angle;
            }
        }
Exemple #3
0
        private static void ProcessPointImpact(GenericPosture posture, CalibrationHelper calibrationHelper, GenericPostureAbstractImpact impact, int handle, PointF old)
        {
            switch (impact.Type)
            {
            case ImpactType.LineAlign:
                AlignPointSegment(posture, impact as GenericPostureImpactLineAlign);
                break;

            case ImpactType.VerticalAlign:
                AlignPointVertical(posture, calibrationHelper, handle, impact as GenericPostureImpactVerticalAlign);
                break;

            case ImpactType.HorizontalAlign:
                AlignPointHorizontal(posture, handle, impact as GenericPostureImpactHorizontalAlign);
                break;

            case ImpactType.Pivot:
                // Get rotation that was applied. Apply same rotation on all points.
                GenericPostureImpactPivot impactPivot = impact as GenericPostureImpactPivot;
                if (impact != null)
                {
                    PointF a       = posture.PointList[impactPivot.Pivot];
                    PointF b       = old;
                    PointF c       = posture.PointList[posture.Handles[handle].Reference];
                    float  radians = GeometryHelper.GetAngle(a, b, c);
                    PivotPoints(posture, radians, impact as GenericPostureImpactPivot);
                }
                break;

            case ImpactType.KeepAngle:
                KeepPointAngle(posture, impact as GenericPostureImpactKeepAngle);
                break;

            case ImpactType.SegmentCenter:
                SegmentCenter(posture, calibrationHelper, impact as GenericPostureImpactSegmentCenter);
                break;

            case ImpactType.PerdpendicularAlign:
                AlignPointPerpendicular(posture, calibrationHelper, impact as GenericPosturePerpendicularAlign);
                break;

            case ImpactType.ParallelAlign:
                AlignPointParallel(posture, calibrationHelper, impact as GenericPostureParallelAlign);
                break;
            }
        }
Exemple #4
0
        private static void PrepareImpacts(GenericPosture posture, int handle)
        {
            foreach (GenericPostureAbstractImpact impact in posture.Handles[handle].Impacts)
            {
                // If there is a KeepAngle impact, we'll later need to know the current angle.
                if (impact.Type == ImpactType.KeepAngle)
                {
                    GenericPostureImpactKeepAngle impactKeepAngle = impact as GenericPostureImpactKeepAngle;

                    PointF origin = posture.PointList[impactKeepAngle.Origin];
                    PointF leg1   = posture.PointList[impactKeepAngle.Leg1];
                    PointF leg2   = posture.PointList[impactKeepAngle.Leg2];

                    if (origin == leg1 || origin == leg2)
                    {
                        continue;
                    }

                    impactKeepAngle.OldAngle    = GeometryHelper.GetAngle(origin, leg1, leg2);
                    impactKeepAngle.OldDistance = GeometryHelper.GetDistance(origin, leg2);
                }
            }
        }
Exemple #5
0
        private void ComputeAngles(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Dictionary <string, FilteredTrajectory> trajs, AngleOptions angleOptions)
        {
            for (int i = 0; i < tsc.Length; i++)
            {
                PointF o = PointF.Empty;
                PointF a = PointF.Empty;
                PointF b = PointF.Empty;

                if (trajs["o"].CanFilter)
                {
                    o = trajs["o"].Coordinates(i);
                    a = trajs["a"].Coordinates(i);
                    b = trajs["b"].Coordinates(i);
                }
                else
                {
                    o = trajs["o"].RawCoordinates(i);
                    a = trajs["a"].RawCoordinates(i);
                    b = trajs["b"].RawCoordinates(i);
                }

                // Compute the actual angle value. The logic here should match the one in AngleHelper.Update().
                // They work on different type of inputs so it's difficult to factorize the functions.
                if (angleOptions.Supplementary)
                {
                    // Create a new point by point reflection of a around o.
                    PointF c = new PointF(2 * o.X - a.X, 2 * o.Y - a.Y);
                    a = b;
                    b = c;
                }

                float angle = 0;
                if (angleOptions.CCW)
                {
                    angle = GeometryHelper.GetAngle(o, a, b);
                }
                else
                {
                    angle = GeometryHelper.GetAngle(o, b, a);
                }

                if (!angleOptions.Signed && angle < 0)
                {
                    angle = (float)(TAU + angle);
                }

                positions[i] = angle;
                radii[i]     = GeometryHelper.GetDistance(o, b);

                tsc[Kinematics.AngularPosition][i] = calibrationHelper.ConvertAngle(angle);

                if (i == 0)
                {
                    tsc[Kinematics.AngularDisplacement][i]      = 0;
                    tsc[Kinematics.TotalAngularDisplacement][i] = 0;
                }
                else
                {
                    float totalDisplacementAngle = angle - positions[0];
                    float displacementAngle      = angle - positions[i - 1];
                    tsc[Kinematics.AngularDisplacement][i]      = calibrationHelper.ConvertAngle(displacementAngle);
                    tsc[Kinematics.TotalAngularDisplacement][i] = calibrationHelper.ConvertAngle(totalDisplacementAngle);
                }
            }
        }