/// <summary>
        /// Takes a scalar in image space and returns a scalar in world space.
        /// Not suitable for geometry.
        /// </summary>
        public float GetScalar(float v)
        {
            PointF a = GetPoint(PointF.Empty);
            PointF b = GetPoint(new PointF(v, 0));

            float d = GeometryHelper.GetDistance(a, b);

            return(v < 0 ? -d : d);
        }
Example #2
0
        /// <summary>
        /// Takes a scalar value in world space and return it in image space.
        /// Not suitable for geometry.
        /// </summary>
        public float GetImageScalar(float v)
        {
            PointF a = distortionHelper.Distort(calibrator.Untransform(PointF.Empty));
            PointF b = distortionHelper.Distort(calibrator.Untransform(new PointF(v, 0)));

            float d = GeometryHelper.GetDistance(a, b);

            return(v < 0 ? -d : d);
        }
Example #3
0
        /// <summary>
        /// Takes two points in image coordinates and return the length of the segment in real world units.
        /// </summary>
        public string GetLengthText(PointF p1, PointF p2, bool precise, bool abbreviation)
        {
            float  length        = GeometryHelper.GetDistance(GetPoint(p1), GetPoint(p2));
            string valueTemplate = precise ? "{0:0.00}" : "{0:0}";
            string text          = String.Format(valueTemplate, length);

            if (abbreviation)
            {
                text = text + " " + String.Format("{0}", UnitHelper.LengthAbbreviation(lengthUnit));
            }

            return(text);
        }
Example #4
0
        public void WriteXml(XmlWriter w, SerializationFilter filter)
        {
            if (ShouldSerializeCore(filter))
            {
                w.WriteElementString("Start", XmlHelper.WritePointF(points["a"]));
                w.WriteElementString("End", XmlHelper.WritePointF(points["b"]));

                TypeConverter enumConverter = TypeDescriptor.GetConverter(typeof(TrackExtraData));
                string        xmlExtraData  = enumConverter.ConvertToString(trackExtraData);
                w.WriteElementString("ExtraData", xmlExtraData);

                w.WriteStartElement("MeasureLabel");
                miniLabel.WriteXml(w);
                w.WriteEndElement();
            }

            if (ShouldSerializeStyle(filter))
            {
                w.WriteStartElement("DrawingStyle");
                style.WriteXml(w);
                w.WriteEndElement();
            }

            if (ShouldSerializeFading(filter))
            {
                w.WriteStartElement("InfosFading");
                infosFading.WriteXml(w);
                w.WriteEndElement();
            }

            if (ShouldSerializeAll(filter))
            {
                // Spreadsheet support.
                w.WriteStartElement("Measure");

                PointF a = CalibrationHelper.GetPoint(new PointF(points["a"].X, points["a"].Y));
                PointF b = CalibrationHelper.GetPoint(new PointF(points["b"].X, points["b"].Y));

                float  len            = GeometryHelper.GetDistance(a, b);
                string value          = String.Format("{0:0.00}", len);
                string valueInvariant = String.Format(CultureInfo.InvariantCulture, "{0:0.00}", len);

                w.WriteAttributeString("UserLength", value);
                w.WriteAttributeString("UserLengthInvariant", valueInvariant);
                w.WriteAttributeString("UserUnitLength", CalibrationHelper.GetLengthAbbreviation());

                w.WriteEndElement();
            }
        }
Example #5
0
        private void ComputeTotalDistance(TrajectoryKinematics kinematics, CalibrationHelper calibrationHelper)
        {
            float distance = 0;

            kinematics.TotalDistance[0] = distance;

            for (int i = 1; i < kinematics.Length; i++)
            {
                PointF a = kinematics.Coordinates(i - 1);
                PointF b = kinematics.Coordinates(i);
                float  d = GeometryHelper.GetDistance(a, b);
                distance += d;
                kinematics.TotalDistance[i] = distance;
            }
        }
Example #6
0
        public void WriteXml(XmlWriter w, SerializationFilter filter)
        {
            if (ShouldSerializeCore(filter))
            {
                w.WriteElementString("Start", XmlHelper.WritePointF(points["a"]));
                w.WriteElementString("End", XmlHelper.WritePointF(points["b"]));
                w.WriteElementString("MeasureVisible", ShowMeasurableInfo.ToString().ToLower());
            }

            if (ShouldSerializeStyle(filter))
            {
                w.WriteStartElement("DrawingStyle");
                style.WriteXml(w);
                w.WriteEndElement();
            }

            if (ShouldSerializeFading(filter))
            {
                w.WriteStartElement("InfosFading");
                infosFading.WriteXml(w);
                w.WriteEndElement();
            }


            if (ShouldSerializeAll(filter))
            {
                // Spreadsheet support.
                w.WriteStartElement("Measure");

                PointF a = CalibrationHelper.GetPoint(new PointF(points["a"].X, points["a"].Y));
                PointF b = CalibrationHelper.GetPoint(new PointF(points["b"].X, points["b"].Y));

                float  len            = GeometryHelper.GetDistance(a, b);
                string value          = String.Format("{0:0.00}", len);
                string valueInvariant = String.Format(CultureInfo.InvariantCulture, "{0:0.00}", len);

                w.WriteAttributeString("UserLength", value);
                w.WriteAttributeString("UserLengthInvariant", valueInvariant);
                w.WriteAttributeString("UserUnitLength", CalibrationHelper.GetLengthAbbreviation());

                w.WriteEndElement();
            }
        }
Example #7
0
        /// <summary>
        /// Build a quadrilateral from a single line.
        /// The quadrilateral will be a square with the original line at the bottom edge.
        /// </summary>
        private QuadrilateralF MakeQuad(PointF start, PointF end, CalibrationAxis calibrationAxis)
        {
            switch (calibrationAxis)
            {
            case CalibrationAxis.LineHorizontal:
            {
                // Rebuild a quadrilateral as a square, assuming the passed line is the bottom edge, left to right.
                // The base quadrilateral is defined as ABCD going CW from top-left,
                // the line is making up the DC vector which will map to the +X axis.
                PointF d = start;
                PointF c = end;
                PointF a = new PointF(d.X + (c.Y - d.Y), d.Y - (c.X - d.X));
                PointF b = new PointF(a.X + (c.X - d.X), a.Y + (c.Y - d.Y));
                return(new QuadrilateralF(a, b, c, d));
            }

            case CalibrationAxis.LineVertical:
            {
                // Rebuild a quadrilateral as a square, assuming the passed line is the left edge, bottom to top.
                // The base quadrilateral is defined as ABCD going CW from top-left,
                // the line is making up the DA vector which will map to the +Y axis.
                PointF d = start;
                PointF a = end;
                PointF c = new PointF(d.X + (d.Y - a.Y), d.Y + (a.X - d.X));
                PointF b = new PointF(a.X + (c.X - d.X), a.Y + (c.Y - d.Y));
                return(new QuadrilateralF(a, b, c, d));
            }

            case CalibrationAxis.ImageAxes:
            default:
            {
                // Rebuild a quadrilateral as a square aligned to the normal image axes (except Y goes up).
                // The base quadrilateral is defined as ABCD going CW from top-left,
                // the line length is giving the length of the DC edge of the square.
                float  length = GeometryHelper.GetDistance(start, end);
                PointF d      = start;
                PointF c      = new PointF(d.X + length, d.Y);
                PointF a      = new PointF(d.X + (c.Y - d.Y), d.Y - (c.X - d.X));
                PointF b      = new PointF(a.X + (c.X - d.X), a.Y + (c.Y - d.Y));
                return(new QuadrilateralF(a, b, c, d));
            }
            }
        }
Example #8
0
        private float GetDistance(PointF a, PointF b, Component component)
        {
            float d = 0;

            switch (component)
            {
            case Component.Magnitude:
                d = GeometryHelper.GetDistance(a, b);
                break;

            case Component.Horizontal:
                d = b.X - a.X;
                break;

            case Component.Vertical:
                d = b.Y - a.Y;
                break;
            }

            return(d);
        }
Example #9
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);
                }
            }
        }
Example #10
0
        private static void MovePointHandleAtDistance(GenericPosture posture, int handle, PointF point, GenericPostureConstraintDistanceToPoint constraint, Keys modifiers)
        {
            if (constraint == null)
            {
                MovePointHandleFreely(posture, handle, point);
                return;
            }

            PointF parent   = posture.PointList[constraint.RefPoint];
            PointF child    = posture.PointList[posture.Handles[handle].Reference];
            float  distance = GeometryHelper.GetDistance(parent, child);
            PointF temp     = GeometryHelper.GetPointAtDistance(parent, point, distance);

            int constraintAngleSubdivisions = 8; // (Constraint by 45° steps).

            if ((modifiers & Keys.Shift) == Keys.Shift)
            {
                posture.PointList[posture.Handles[handle].Reference] = GeometryHelper.GetPointAtClosestRotationStepCardinal(parent, temp, constraintAngleSubdivisions);
            }
            else
            {
                posture.PointList[posture.Handles[handle].Reference] = temp;
            }
        }
Example #11
0
        private static CoordinateSystemGrid FindForPlaneCalibration(CalibrationHelper calibrationHelper)
        {
            CoordinateSystemGrid grid        = new CoordinateSystemGrid();
            RectangleF           imageBounds = new RectangleF(PointF.Empty, calibrationHelper.ImageSize);
            RectangleF           clipWindow  = imageBounds;

            CalibrationPlane calibrator = calibrationHelper.CalibrationByPlane_GetCalibrator();

            RectangleF plane = new RectangleF(PointF.Empty, calibrator.Size);

            int   targetSteps    = 15;
            float stepVertical   = 1.0f;
            float stepHorizontal = 1.0f;

            // The extended plane is used for vanishing point replacement and iteration stop condition.
            QuadrilateralF extendedPlane;
            bool           orthogonal;

            if (!calibrator.QuadImage.IsRectangle)
            {
                // If perspective plane, define as 2n times the nominal plane centered on origin.
                orthogonal = false;
                float  n = 4;
                PointF a = new PointF(-calibrator.Size.Width * n, calibrator.Size.Height * n);
                PointF b = new PointF(calibrator.Size.Width * n, calibrator.Size.Height * n);
                PointF c = new PointF(calibrator.Size.Width * n, -calibrator.Size.Height * n);
                PointF d = new PointF(-calibrator.Size.Width * n, -calibrator.Size.Height * n);
                extendedPlane = new QuadrilateralF(a, b, c, d);

                QuadrilateralF quadImage = calibrator.QuadImage;

                float projectedWidthLength   = GeometryHelper.GetDistance(quadImage.A, quadImage.B);
                float scaledTargetHorizontal = targetSteps / (calibrationHelper.ImageSize.Width / projectedWidthLength);
                stepHorizontal = RangeHelper.FindUsableStepSize(plane.Width, scaledTargetHorizontal);

                float projectedHeightLength = GeometryHelper.GetDistance(quadImage.A, quadImage.D);
                float scaledTargetVertical  = targetSteps / (calibrationHelper.ImageSize.Height / projectedHeightLength);
                stepVertical = RangeHelper.FindUsableStepSize(plane.Height, scaledTargetVertical);
            }
            else
            {
                // If flat plane (and no distortion) we know there is no way to get any vanishing point inside the image,
                // so we can safely use the whole image reprojection as an extended plane.
                orthogonal = true;
                QuadrilateralF quadImageBounds = new QuadrilateralF(imageBounds);
                PointF         a = calibrationHelper.GetPointFromRectified(quadImageBounds.A);
                PointF         b = calibrationHelper.GetPointFromRectified(quadImageBounds.B);
                PointF         c = calibrationHelper.GetPointFromRectified(quadImageBounds.C);
                PointF         d = calibrationHelper.GetPointFromRectified(quadImageBounds.D);
                extendedPlane = new QuadrilateralF(a, b, c, d);

                float width = extendedPlane.B.X - extendedPlane.A.X;
                stepHorizontal = RangeHelper.FindUsableStepSize(width, targetSteps);

                float height = extendedPlane.A.Y - extendedPlane.D.Y;
                stepVertical = RangeHelper.FindUsableStepSize(height, targetSteps);
            }

            //-------------------------------------------------------------------------------------------------
            // There is a complication with points behind the camera, as they projects above the vanishing line.
            // The general strategy is the following:
            // Find out if the vanishing point is inside the image. Reminder: parallel lines share the same vanishing point.
            // If it is not inside the image, there is no risk, so we take two points on the line and draw an infinite line that we clip against the image bounds.
            // If it is inside the image:
            // Take two points on the line and project them in image space. They are colinear with the vanishing point in image space.
            // Find on which side of the quadrilateral the vanishing point is.
            // If the vanishing point is above the quad, draw a ray from the top of the extended quad, down to infinity.
            // If the vanishing point is below the quad, draw a ray from the bottom of the extended quad, up to infinity.
            //
            // Stepping strategy:
            // We start at origin and progress horizontally and vertically until we find a gridline that is completely clipped out.
            //-------------------------------------------------------------------------------------------------

            // Vertical lines.
            PointF  yVanish        = new PointF(0, float.MinValue);
            bool    yVanishVisible = false;
            Vector3 yv             = calibrator.Project(new Vector3(0, 1, 0));

            if (yv.Z != 0)
            {
                yVanish        = new PointF(yv.X / yv.Z, yv.Y / yv.Z);
                yVanishVisible = clipWindow.Contains(yVanish);
            }

            CreateVerticalGridLines(grid, 0, -stepHorizontal, calibrator, clipWindow, plane, extendedPlane, orthogonal, yVanishVisible, yVanish);
            CreateVerticalGridLines(grid, stepHorizontal, stepHorizontal, calibrator, clipWindow, plane, extendedPlane, orthogonal, yVanishVisible, yVanish);

            // Horizontal lines
            PointF  xVanish        = new PointF(float.MinValue, 0);
            bool    xVanishVisible = false;
            Vector3 xv             = calibrator.Project(new Vector3(1, 0, 0));

            if (xv.Z != 0)
            {
                xVanish        = new PointF(xv.X / xv.Z, xv.Y / xv.Z);
                xVanishVisible = clipWindow.Contains(xVanish);
            }

            CreateHorizontalGridLines(grid, 0, -stepVertical, calibrator, clipWindow, plane, extendedPlane, orthogonal, xVanishVisible, xVanish);
            CreateHorizontalGridLines(grid, stepVertical, stepVertical, calibrator, clipWindow, plane, extendedPlane, orthogonal, xVanishVisible, xVanish);

            return(grid);
        }
Example #12
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);
                }
            }
        }