Beispiel #1
0
        private void ImportOtherDrawingsData(Metadata metadata)
        {
            LinearKinematics linearKinematics = new LinearKinematics();

            // Trackable drawing's individual points.
            foreach (ITrackable trackable in metadata.TrackableDrawings())
            {
                Dictionary <string, TrackablePoint> trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(trackable);

                if (trackablePoints == null)
                {
                    continue;
                }

                foreach (var pair in trackablePoints)
                {
                    TrackablePoint        tp       = pair.Value;
                    Timeline <TrackFrame> timeline = pair.Value.Timeline;
                    if (timeline.Count == 0)
                    {
                        continue;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    TimeSeriesCollection tsc = linearKinematics.BuildKinematics(traj, metadata.CalibrationHelper);

                    string name  = trackable.Name;
                    Color  color = trackable.Color;

                    // Custom drawings may have dedicated names for their handles.
                    DrawingGenericPosture dgp = trackable as DrawingGenericPosture;
                    if (dgp == null)
                    {
                        name = name + " - " + pair.Key;
                    }
                    else
                    {
                        foreach (var handle in dgp.GenericPostureHandles)
                        {
                            if (handle.Reference.ToString() != pair.Key)
                            {
                                continue;
                            }

                            name  = name + " - " + (string.IsNullOrEmpty(handle.Name) ? pair.Key : handle.Name);
                            color = handle.Color == Color.Transparent ? trackable.Color : handle.Color;
                            break;
                        }
                    }

                    TimeSeriesPlotData data = new TimeSeriesPlotData(name, color, tsc);
                    timeSeriesData.Add(data);
                    filteredTrajectories.Add(data, traj);
                }
            }
        }
Beispiel #2
0
        public TimeSeriesCollection BuildKinematics(FilteredTrajectory traj, CalibrationHelper calibrationHelper)
        {
            TimeSeriesCollection tsc = new TimeSeriesCollection(traj.Length);

            if (traj.Length == 0)
            {
                return(tsc);
            }

            tsc.AddTimes(traj.Times);
            tsc.AddComponent(Kinematics.XRaw, traj.RawXs);
            tsc.AddComponent(Kinematics.YRaw, traj.RawYs);
            tsc.AddComponent(Kinematics.X, traj.Xs);
            tsc.AddComponent(Kinematics.Y, traj.Ys);

            Func <int, PointF> getCoord;

            if (traj.CanFilter)
            {
                getCoord = traj.Coordinates;
            }
            else
            {
                getCoord = traj.RawCoordinates;
            }

            tsc.InitializeKinematicComponents(new List <Kinematics>()
            {
                Kinematics.LinearDistance,
                Kinematics.LinearHorizontalDisplacement,
                Kinematics.LinearVerticalDisplacement,
                Kinematics.LinearSpeed,
                Kinematics.LinearHorizontalVelocity,
                Kinematics.LinearVerticalVelocity,
                Kinematics.LinearAcceleration,
                Kinematics.LinearHorizontalAcceleration,
                Kinematics.LinearVerticalAcceleration,
            });

            ComputeDistances(tsc, calibrationHelper, getCoord);
            ComputeVelocities(tsc, calibrationHelper, getCoord);
            ComputeAccelerations(tsc, calibrationHelper, getCoord);

            return(tsc);
        }
Beispiel #3
0
        public static Circle Fit(FilteredTrajectory traj)
        {
            if (traj.Length < 3)
            {
                return(Circle.Empty);
            }

            // 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 = traj.Length;
            Matrix <double> m    = Matrix <double> .Build.Dense(rows, 3);

            Matrix <double> v = Matrix <double> .Build.Dense(rows, 1);

            for (int i = 0; i < rows; i++)
            {
                PointF point = traj.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;
            }

            try
            {
                Matrix <double> mt = m.Clone().Transpose();
                Matrix <double> b  = mt.Multiply(m);
                Matrix <double> c  = mt.Multiply(v);
                Matrix <double> 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));

                return(new Circle(center, (float)radius));
            }
            catch (InvalidOperationException)
            {
                return(Circle.Empty);
            }
        }
Beispiel #4
0
        private static void ImportAngleDrawingsData(Metadata metadata, List <TimeSeriesPlotData> timeSeriesData)
        {
            // Create three filtered trajectories named o, a, b directly based on the trackable points.
            foreach (DrawingAngle drawingAngle in metadata.Angles())
            {
                Dictionary <string, FilteredTrajectory> trajs           = new Dictionary <string, FilteredTrajectory>();
                Dictionary <string, TrackablePoint>     trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(drawingAngle);

                bool tracked = true;

                foreach (string key in trackablePoints.Keys)
                {
                    Timeline <TrackFrame> timeline = trackablePoints[key].Timeline;
                    if (timeline.Count == 0)
                    {
                        tracked = false;
                        break;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    trajs.Add(key, traj);
                }

                if (!tracked)
                {
                    continue;
                }

                TimeSeriesCollection tsc  = angularKinematics.BuildKinematics(trajs, drawingAngle.AngleOptions, metadata.CalibrationHelper);
                TimeSeriesPlotData   data = new TimeSeriesPlotData(drawingAngle.Name, drawingAngle.Color, tsc);
                timeSeriesData.Add(data);
            }
        }
Beispiel #5
0
        private PlotModel CreateCutoffPlot(IEnumerable <TimeSeriesPlotData> timeSeriesPlotData)
        {
            if (timeSeriesPlotData == null)
            {
                return(null);
            }

            PlotModel model = new PlotModel();

            model.TitleFontSize = 12;
            model.Title         = "Residuals autocorrelation";

            LinearAxis xAxis = new LinearAxis();

            xAxis.Position           = AxisPosition.Bottom;
            xAxis.MajorGridlineStyle = LineStyle.Solid;
            xAxis.MinorGridlineStyle = LineStyle.Dot;
            xAxis.Title         = "Cutoff frequency (Hz)";
            xAxis.TitleFontSize = 10;
            model.Axes.Add(xAxis);

            LinearAxis yAxis = new LinearAxis();

            yAxis.Position           = AxisPosition.Left;
            yAxis.MajorGridlineStyle = LineStyle.Solid;
            yAxis.MinorGridlineStyle = LineStyle.Dot;
            yAxis.Title         = "Autocorrelation (normalized)";
            yAxis.TitleFontSize = 10;
            yAxis.Maximum       = 1.0f;
            model.Axes.Add(yAxis);

            lvCutoffFrequencies.Items.Clear();

            foreach (TimeSeriesPlotData tspd in timeSeriesPlotData)
            {
                if (!filteredTrajectories.ContainsKey(tspd) || !filteredTrajectories[tspd].CanFilter)
                {
                    continue;
                }

                // X=red and Y=green matches the typical mapping used in 3D apps.
                LineSeries xseries = new LineSeries();
                xseries.Color      = OxyColors.Tomato;
                xseries.MarkerType = MarkerType.None;
                xseries.Smooth     = true;

                LineSeries yseries = new LineSeries();
                yseries.Color      = OxyColors.Green;
                yseries.MarkerType = MarkerType.None;
                yseries.Smooth     = true;

                FilteredTrajectory ft = filteredTrajectories[tspd];

                foreach (FilteringResult r in ft.FilterResultXs)
                {
                    xseries.Points.Add(new DataPoint(r.CutoffFrequency, r.DurbinWatson));
                }

                foreach (FilteringResult r in ft.FilterResultYs)
                {
                    yseries.Points.Add(new DataPoint(r.CutoffFrequency, r.DurbinWatson));
                }

                model.Series.Add(xseries);
                model.Series.Add(yseries);

                // Filtering tab.
                if (ft.XCutoffIndex >= 0 && ft.YCutoffIndex >= 0)
                {
                    double xcutoff    = ft.FilterResultXs[ft.XCutoffIndex].CutoffFrequency;
                    double ycutoff    = ft.FilterResultXs[ft.YCutoffIndex].CutoffFrequency;
                    string strXCutoff = string.Format("{0:0.000}", xcutoff);
                    string strYCutoff = string.Format("{0:0.000}", ycutoff);
                    lvCutoffFrequencies.Items.Add(new ListViewItem(new string[] { tspd.Label, strXCutoff, strYCutoff }));
                }
            }

            return(model);
        }
Beispiel #6
0
        private static void ImportCustomDrawingsData(Metadata metadata, List <TimeSeriesPlotData> timeSeriesData)
        {
            // Collect angular trajectories for all the angles in all the custom tools.

            foreach (DrawingGenericPosture drawing in metadata.GenericPostures())
            {
                Dictionary <string, TrackablePoint> trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(drawing);

                // First create trajectories for all the trackable points in the drawing.
                // This avoids duplicating the filtering operation for points shared by more than one angle.
                // Here the trajectories are indexed by the original alias in the custom tool, based on the index.
                Dictionary <string, FilteredTrajectory> trajs = new Dictionary <string, FilteredTrajectory>();
                bool tracked = true;

                foreach (string key in trackablePoints.Keys)
                {
                    Timeline <TrackFrame> timeline = trackablePoints[key].Timeline;

                    if (timeline.Count == 0)
                    {
                        // The point is trackable but doesn't have any timeline data.
                        // This happens if the user is not tracking that drawing, so we don't need to go further.
                        tracked = false;
                        break;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    trajs.Add(key, traj);
                }

                if (!tracked)
                {
                    continue;
                }

                // Loop over all angles in this drawing and find the trackable aliases of the points making up the particular angle.
                // The final collection of trajectories for each angle should have indices named o, a, b.
                foreach (GenericPostureAngle gpa in drawing.GenericPostureAngles)
                {
                    // From integer indices to tracking aliases.
                    string keyO = gpa.Origin.ToString();
                    string keyA = gpa.Leg1.ToString();
                    string keyB = gpa.Leg2.ToString();

                    // All points in an angle must be trackable as there is currently no way to get the static point coordinate.
                    if (!trajs.ContainsKey(keyO) || !trajs.ContainsKey(keyA) || !trajs.ContainsKey(keyB))
                    {
                        continue;
                    }

                    // Remap to oab.
                    Dictionary <string, FilteredTrajectory> angleTrajs = new Dictionary <string, FilteredTrajectory>();
                    angleTrajs.Add("o", trajs[keyO]);
                    angleTrajs.Add("a", trajs[keyA]);
                    angleTrajs.Add("b", trajs[keyB]);

                    AngleOptions         options = new AngleOptions(gpa.Signed, gpa.CCW, gpa.Supplementary);
                    TimeSeriesCollection tsc     = angularKinematics.BuildKinematics(angleTrajs, options, metadata.CalibrationHelper);

                    string name = drawing.Name;
                    if (!string.IsNullOrEmpty(gpa.Name))
                    {
                        name = name + " - " + gpa.Name;
                    }

                    Color color             = gpa.Color == Color.Transparent ? drawing.Color : gpa.Color;
                    TimeSeriesPlotData data = new TimeSeriesPlotData(name, color, tsc);

                    timeSeriesData.Add(data);
                }
            }
        }