예제 #1
0
        /// <summary>
        /// Loads the given KMZ or KMX and store it in mTrackData.
        /// </summary>
        private void parseKmxOrKmz(string kmxPath)
        {
            mTrackData = null;

            try {
                XmlDocument doc = new XmlDocument();

                if (ZipFile.IsZipFile(kmxPath))
                {
                    using (ZipFile zf = ZipFile.Read(kmxPath)) {
                        foreach (ZipEntry ze in zf)
                        {
                            // We take the first name that ends with .kmx
                            if (ze.FileName.EndsWith(".kml"))
                            {
                                mLabelTrackDataLoadResults.Text = "Parsing " + ze.FileName;
                                Application.DoEvents();

                                MemoryStream ms = new MemoryStream();
                                ze.Extract(ms);
                                ms.Seek(0, SeekOrigin.Begin);

                                doc.Load(ms);
                                mTrackData = new TrackParser(doc);
                            }
                        }
                    }
                }
                else
                {
                    // Read the kml file directly
                    mLabelTrackDataLoadResults.Text = "Parsing " + Path.GetFileName(kmxPath);
                    Application.DoEvents();

                    doc.Load(kmxPath);
                    mTrackData = new TrackParser(doc);
                }

                mLabelTrackDataLoadResults.Text = mTrackData.Summary;
            } catch (FileNotFoundException) {
                mLabelTrackDataLoadResults.Text = "File not found";
            } catch (Exception e) {
                mLabelTrackDataLoadResults.Text = "Error: " + e.Message;
                Log("Failed to load " + kmxPath + ": " + e.Message + "\n" + e.StackTrace);
            }

            mStatusBar.Text = null;
        }
예제 #2
0
 /// <summary>
 /// Creates a new generator.
 /// Note that for a preview you just use destFilename=null.
 /// </summary>
 /// <param name="fps">The desired frames per second, e.g. 30</param>
 /// <param name="movieSx">Movie container width in pixels</param>
 /// <param name="movieSy">Movie container height in pixels</param>
 /// <param name="trackSx">Track rendering width in pixels</param>
 /// <param name="trackSy">Track rendering height in pixels</param>
 /// <param name="trackData">Track data</param>
 /// <param name="destFilename">AVI destination filename. Null for a preview.</param>
 public Generator(int fps,
                  int movieSx,
                  int movieSy,
                  int trackSx,
                  int trackSy,
                  TrackParser trackData,
                  string destFilename)
 {
     mFps          = fps;
     mMovieSx      = movieSx;
     mMovieSy      = movieSy;
     mTrackSx      = trackSx;
     mTrackSy      = trackSy;
     mTrackData    = trackData;
     mDestFilename = destFilename;
 }
예제 #3
0
        public Interpolator(TrackParser trackData)
        {
            mTrackData = trackData;

            mCurrInterpol = new TrackParser.Sample();
        }
예제 #4
0
        private Bitmap prepareTrackBmp(Rectangle trackRect, Gps2PixelProjection trackProj, TrackParser td)
        {
            // We need at least a lap to draw something
            if (!td.HasSamples || trackProj == null)
            {
                return(null);
            }

            // We'll draw one of the laps. Just get the first lap.
            TrackParser.Lap currLap = td.Laps[0];

            int    w   = trackRect.Width;
            int    h   = trackRect.Height;
            Bitmap bmp = new Bitmap(w, h);

            using (Graphics g = Graphics.FromImage(bmp)) {
                using (Brush bgColor = new SolidBrush(Color.Gray),
                       trackColor = new SolidBrush(Color.Yellow)) {
                    using (Pen trackPen = new Pen(trackColor, kTrackWidth)) {
                        g.FillRectangle(bgColor, 0, 0, w, h);

                        List <TrackParser.Sample> samples = td.Samples;
                        TrackParser.Sample        s       = samples[0];
                        CPointF last = new CPointF();
                        CPointF next = new CPointF();

                        transformGpsCoord(s.mLongtiude, s.mLatitude, trackProj, last);

                        float px = (float)trackProj.mPixelOffsetX;
                        float py = (float)trackProj.mPixelOffsetY;

                        last.mX -= px;
                        last.mY -= py;

                        for (int i = 1, n = samples.Count; i < n; i++)
                        {
                            s = samples[i];
                            if (s.mLap != currLap)
                            {
                                continue;
                            }

                            transformGpsCoord(s.mLongtiude, s.mLatitude, trackProj, next);
                            next.mX -= px;
                            next.mY -= py;

                            g.DrawLine(trackPen, last.mX, last.mY, next.mX, next.mY);

                            last.mX = next.mX;
                            last.mY = next.mY;
                        }
                    }
                }
            }

            return(bmp);
        }
예제 #5
0
        // --- GPS to track rect & bitmap ---

        private Gps2PixelProjection prepareTrackProj(Rectangle rect, TrackParser td, out Rectangle trackRect)
        {
            // we need at least one point to do something
            if (!td.HasSamples)
            {
                trackRect = Rectangle.Empty;
                return(null);
            }

            double minLong = Double.PositiveInfinity,
                   maxLong = Double.NegativeInfinity,
                   minLat  = Double.PositiveInfinity,
                   maxLat  = Double.NegativeInfinity;

            foreach (TrackParser.Sample d in td.Samples)
            {
                minLong = Math.Min(minLong, d.mLongtiude);
                maxLong = Math.Max(maxLong, d.mLongtiude);
                minLat  = Math.Min(minLat, d.mLatitude);
                maxLat  = Math.Max(maxLat, d.mLatitude);
            }

            // we want to map the min..maxLong(+X)..Lat(-Y) to the given rect
            // rect top left corner (it's x/y base) corresponds to minLong/maxLat.

            float x = rect.X;
            float y = rect.Y;
            float w = rect.Width;
            float h = rect.Height;

            // currently use a square part of the dest rect
            if (w > h)
            {
                w = h;
            }
            else
            {
                h = w;
            }

            // adjust for track border
            x += kTrackBorder;
            y += kTrackBorder;
            w -= 2 * kTrackBorder;
            h -= 2 * kTrackBorder;

            trackRect = new Rectangle((int)x, (int)y, (int)w, (int)h);

            // Compute offset and scaling to transform a coord point into a screen point

            Gps2PixelProjection proj = new Gps2PixelProjection();

            proj.mGpsOffsetX = minLong;
            proj.mGpsOffsetY = maxLat;

            proj.mPixelOffsetX = x;
            proj.mPixelOffsetY = y;

            proj.mGpsScaleX = (maxLong > minLong) ? w / (maxLong - minLong) : 0;
            proj.mGpsScaleY = (maxLat > minLat) ? h / (minLat - maxLat) : 0;

            return(proj);
        }
예제 #6
0
        private void threadEntryPoint()
        {
            int         fps = mFps;
            int         msx = mMovieSx;
            int         msy = mMovieSy;
            int         tsx = mTrackSx;
            int         tsy = mTrackSy;
            TrackParser td  = mTrackData;

            using (Graphics g = Graphics.FromImage(mAviBmp)) {
                using (Brush chromaColor = new SolidBrush(Color.Blue),
                       bgColor = new SolidBrush(Color.Gray),
                       posColor = new SolidBrush(Color.Red),
                       textColor = new SolidBrush(Color.Orange)) {
                    Rectangle bgRect = new Rectangle(msx - tsx, msy - tsy, tsx, tsy);

                    int nbFrames = (int)(mTrackData.TotalTime * fps);

                    // prepare track drawing (map GPS coord => screen coord: offset + scale)
                    Rectangle           trackRect;
                    Gps2PixelProjection trackProj = prepareTrackProj(bgRect, td, out trackRect);
                    Bitmap trackBmp = prepareTrackBmp(trackRect, trackProj, td);

                    // prepare g-meter pos

                    // prepare text positions

                    PointF[] textPos;
                    using (Font labelFont = prepareText(bgRect, out textPos),
                           numFont = new Font(FontFamily.GenericMonospace, labelFont.Size, FontStyle.Bold)) {
                        Interpolator interp = new Interpolator(td);

                        double invFps = 1 / (double)fps;

                        bool userStopRequested = false;

                        for (int frame = 0, updateFps = 0;
                             frame < nbFrames && !userStopRequested;
                             frame++, updateFps++)
                        {
                            double currTime = (double)frame * invFps;

                            TrackParser.Sample currSample = interp.GoTo(currTime);

                            double currLapTime = interp.CurrLapTime;

                            // keep track of current dot & interpolate between dots

                            // draw background

                            g.FillRectangle(chromaColor, 0, 0, msx, msy);

                            g.FillRectangle(bgColor, bgRect);

                            // draw track + current pos
                            drawTrackPos(g, posColor, trackRect, trackBmp, trackProj,
                                         currSample.mLongtiude, currSample.mLatitude);

                            // draw bearing

                            // TODO

                            // draw text
                            drawText(g, textColor, labelFont, numFont, textPos,
                                     currSample.mSpeed, currSample.mAccel, currSample.mLateralAccel,
                                     currTime,
                                     currLapTime, interp.CurrLapIndex, interp.LastLapDuration);

                            // finally dump frame and update preview/progress
                            MainModule.MainForm.Invoke(mAddFrameFunc);

                            if (updateFps == fps)
                            {
                                updateFps = 0;
                            }
                            if (updateFps == 0)
                            {
                                // Update status, progress, etc.
                                userStopRequested = syncUpdate(frame, nbFrames, new Bitmap(mAviBmp));
                            }

                            if (mThreadMustStop)
                            {
                                break;
                            }
                        }
                    } // using Font

                    // Make sure to tell owner that the generator is done
                    // This one must be async -- this thread will quit and the owner will
                    // try to join to wait for the thread to finish.
                    asyncUpdate(nbFrames, nbFrames, new Bitmap(mAviBmp));
                } // using Brush
            }     // using Graphics
        }