Example #1
0
        public void HitTest()
        {
            SymbolDB     symbolDB = new SymbolDB(Util.GetFileInAppDirectory("symbols.xml"));
            UndoMgr      undomgr  = new UndoMgr(5);
            EventDB      eventDB  = new EventDB(undomgr);
            CourseView   courseView;
            CourseLayout course;

            eventDB.Load(TestUtil.GetTestFile("courselayout\\marymoor1.coursescribe"));
            eventDB.Validate();

            // Create the all controls course
            courseView = CourseView.CreateViewingCourseView(eventDB, CourseDesignator.AllControls);
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);

            CheckHitTest(course, new PointF(9.0F, 12.4F), 0, null, "Water:          special:1  scale:1  location:(7.996275,12.34392)");
            CheckHitTest(course, new PointF(54.7F, 12.2F), 0, null, null);
            CheckHitTest(course, new PointF(0.5F, 9.0F), 0, null, "Control:        control:72  scale:1  location:(-0.7,10.3)  gaps:");
            CheckHitTest(course, new PointF(58.5F, -9.2F), 0, null, "Start:          control:1  scale:1  location:(56.8,-8.7)  orientation:0");
            CheckHitTest(course, new PointF(46.6F, -15.9F), 0, null, @"Code:           control:52  scale:1  text:52  top-left:(45.56,-12.18)
                font-name:Roboto Condensed  font-style:Bold  font-height:4.18");

            // Create course 3
            courseView = CourseView.CreateViewingCourseView(eventDB, new CourseDesignator(CourseId(3)));
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);

            CheckHitTest(course, new PointF(-3.5F, 10.3F), 0, null, "Control:        control:72  course-control:305  scale:1  location:(-0.7,10.3)  gaps:");
            CheckHitTest(course, new PointF(35.6F, 17.7F), 0, null, null);
            CheckHitTest(course, new PointF(59.2F, 18.5F), 0, null, "Leg:            control:71  course-control:307  scale:1  course-control2:308  path:N(42.92,17.55)--N(71.88,19.05)");
            CheckHitTest(course, new PointF(72.1F, 33.5F), 0, null, @"ControlNumber:  control:75  course-control:311  scale:1  text:10  top-left:(66.57,37.12)
                font-name:Roboto  font-style:Regular  font-height:5.57");
            CheckHitTest(course, new PointF(50.2F, -2.9F), 0, null, @"Finish:         control:2  course-control:315  scale:1  location:(53.2,-2.8)  gaps:");

            // Add in all controls.  Test with true and false for all Layers.
            courseView = CourseView.CreateFilteredAllControlsView(eventDB, new CourseDesignator[] { Designator(3) }, ControlPointKind.Normal,
                                                                  new CourseViewOptions()
            {
                showNonDescriptionSpecials = false, showDescriptionSpecials = true
            });
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, CourseLayer.AllControls);

            CheckHitTest(course, new PointF(5.1F, -5.1F), CourseLayer.All, null, @"Control:        layer:12  control:76  scale:1  location:(5.6,-5.7)  gaps:");
            CheckHitTest(course, new PointF(5.1F, -5.1F), CourseLayer.MainCourse, null, null);

            // Test the type filter
            CheckHitTest(course, new PointF(59.2F, 18.5F), CourseLayer.MainCourse, (co => co is LegCourseObj), "Leg:            control:71  course-control:307  scale:1  course-control2:308  path:N(42.92,17.55)--N(71.88,19.05)");
            CheckHitTest(course, new PointF(59.2F, 18.5F), CourseLayer.MainCourse, (co => co is PointCourseObj), null);
            CheckHitTest(course, new PointF(-3.5F, 10.3F), CourseLayer.MainCourse, (co => co is PointCourseObj), "Control:        control:72  course-control:305  scale:1  location:(-0.7,10.3)  gaps:");
            CheckHitTest(course, new PointF(-3.5F, 10.3F), CourseLayer.MainCourse, (co => co is LineCourseObj), null);
        }
Example #2
0
 public AddTextMode(Controller controller, UndoMgr undoMgr, SelectionMgr selectionMgr, EventDB eventDB, string text, string fontName, bool fontBold, bool fontItalic, SpecialColor fontColor, float fontHeight)
 {
     this.controller   = controller;
     this.undoMgr      = undoMgr;
     this.selectionMgr = selectionMgr;
     this.eventDB      = eventDB;
     this.text         = text;
     this.fontName     = fontName;
     this.fontBold     = fontBold;
     this.fontItalic   = fontItalic;
     this.fontColor    = fontColor;
     this.fontHeight   = fontHeight;
     this.displayText  = CourseFormatter.ExpandText(eventDB, selectionMgr.ActiveCourseView, text);
 }
Example #3
0
        // Create a leg object from one point to another. Might return null. The controlIds can be None, but if they are supplied, then
        // they are used to handle bends. If either is null, the leg object is just straight. Gaps are never displayed.
        private static LegCourseObj CreateLegHighlight(EventDB eventDB, PointF pt1, ControlPointKind kind1, Id <ControlPoint> controlId1, PointF pt2, ControlPointKind kind2, Id <ControlPoint> controlId2, float courseObjRatio, CourseAppearance appearance)
        {
            LegGap[] gaps;

            SymPath path = CourseFormatter.GetLegPath(eventDB, pt1, kind1, controlId1, pt2, kind2, controlId2, float.NaN, courseObjRatio, appearance, out gaps);

            if (path != null)
            {
                return(new LegCourseObj(controlId1, Id <CourseControl> .None, Id <CourseControl> .None, courseObjRatio, appearance, path, null));     // We never display the gaps, because it looks dumb.
            }
            else
            {
                return(null);
            }
        }
Example #4
0
        public void BoundingRect()
        {
            SymbolDB     symbolDB = new SymbolDB(Util.GetFileInAppDirectory("symbols.xml"));
            UndoMgr      undomgr  = new UndoMgr(5);
            EventDB      eventDB  = new EventDB(undomgr);
            CourseView   courseView;
            CourseLayout course;

            eventDB.Load(TestUtil.GetTestFile("courselayout\\marymoor1.coursescribe"));
            eventDB.Validate();

            // Create the all controls course
            courseView = CourseView.CreateViewingCourseView(eventDB, CourseDesignator.AllControls);
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);
            RectangleF bounding = course.BoundingRect();
            RectangleF expected = new RectangleF(-16.41F, -34.3F, 152.17F, 79.95F);

            TestUtil.AssertEqualRect(expected, bounding, 0.01F, "Bounding rect all controls");

            // Try course 1
            courseView = CourseView.CreateViewingCourseView(eventDB, new CourseDesignator(CourseId(1)));
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);
            bounding = course.BoundingRect();
            expected = new RectangleF(-2.11F, -32.9F, 64.73F, 60.43F);
            TestUtil.AssertEqualRect(expected, bounding, 0.1F, "Bounding rect course 1");

            // Try course with control descriptions on it.
            courseView = CourseView.CreateViewingCourseView(eventDB, new CourseDesignator(CourseId(10)));
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);
            bounding = course.BoundingRect();
            expected = new RectangleF(6.0F, -40.1F, 121.94F, 77.22F);
            TestUtil.AssertEqualRect(expected, bounding, 0.1F, "Bounding rect course 10");

            // Do an empty course
            courseView = CourseView.CreateViewingCourseView(eventDB, new CourseDesignator(CourseId(11)));
            course     = new CourseLayout();
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, 0);
            bounding = course.BoundingRect();
            expected = RectangleF.FromLTRB(0, 0, 0, 0);
            TestUtil.AssertEqualRect(expected, bounding, 0.001F, "Bounding rect blank course");
        }
Example #5
0
        // The core printing routine.
        void DrawPage(IGraphicsTarget graphicsTarget, CoursePage page)
        {
            // Get the course view for the course we are printing.
            CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator);

            // Get the correct purple color to print the course in.
            short ocadId;
            float purpleC, purpleM, purpleY, purpleK;
            bool  purpleOverprint;

            FindPurple.GetPurpleColor(mapDisplay, appearance, out ocadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint);

            // Create a course layout from the view.
            CourseLayout layout = new CourseLayout();

            layout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
            layout.SetLayerColor(CourseLayer.MainCourse, ocadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, purpleOverprint);
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, CourseLayer.MainCourse);

            // Set the course layout into the map display
            mapDisplay.SetCourse(layout);
            mapDisplay.SetPrintArea(null);

            // Set the transform, and the clip.
            Matrix transform = Geometry.CreateInvertedRectangleTransform(page.mapRectangle, page.printRectangle);

            PushRectangleClip(graphicsTarget, page.printRectangle);
            graphicsTarget.PushTransform(transform);
            // Determine the resolution in map coordinates.
            Matrix inverseTransform = transform.Clone();

            inverseTransform.Invert();
            float minResolutionPage = 100F / 2400F;  // Assume 2400 DPI as the base resolution, to get very accurate print.
            float minResolutionMap  = Geometry.TransformDistance(minResolutionPage, inverseTransform);

            // And draw.
            mapDisplay.Draw(graphicsTarget, page.mapRectangle, minResolutionMap);

            graphicsTarget.PopTransform();
            graphicsTarget.PopClip();
        }
Example #6
0
        // Udate the selected course objects in the course.
        void UpdateSelectedCourseObjects()
        {
            if (selectionKind == SelectionKind.None) {
                selectedCourseObjects = null;
                return;
            }

            List<CourseObj> list = new List<CourseObj>();

            // Get through each object in the active course and find which ones match. Ignore stuff in the All Controls layer.
            foreach (CourseObj courseobj in activeCourse) {
                if (courseobj.layer != CourseLayer.AllControls) {
                    if (selectionKind == SelectionKind.Control &&
                            !(courseobj is LineCourseObj) &&    // don't select legs
                            courseobj.controlId == selectedControl &&
                            courseobj.courseControlId == selectedCourseControl) 
                    {
                        list.Add(courseobj);
                    }
                    else if (selectionKind == SelectionKind.Leg &&
                            courseobj is LineCourseObj &&
                            courseobj.courseControlId == selectedCourseControl &&
                            ((LineCourseObj) courseobj).courseControlId2 == selectedCourseControl2) 
                    {
                        // The leg may be made up of multiple parts due to flagging and gaps. Create a single course object for the whole thing.
                        CourseObj legObject = CourseFormatter.CreateSimpleLeg(eventDB, activeCourseView, courseobj.courseObjRatio, courseobj.appearance, selectedCourseControl, selectedCourseControl2);
                        if (legObject != null)
                            list.Add(legObject);
                        break;
                    }
                    else if (selectionKind == SelectionKind.Special &&
                        courseobj.specialId == selectedSpecial) 
                    {
                        list.Add(courseobj);
                    }
                }
            }

            selectedCourseObjects = list.ToArray();
        }
Example #7
0
        // Update the course
        void UpdateCourse()
        {
            CourseAppearance appearance = controller.GetCourseAppearance();

            // Get purple color.
            short purpleOcadId;
            float purpleC, purpleM, purpleY, purpleK;
            bool purpleOverprint;
            controller.GetPurpleColor(out purpleOcadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint);

            // Place the active course in the layout.
            activeCourse = new CourseLayout();
            activeCourse.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
            activeCourse.SetLayerColor(CourseLayer.MainCourse, NormalCourseAppearance.courseOcadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, 
                                       (purpleOverprint && (extraCourses == null || extraCourses.Count == 0))); 
            CourseFormatter.FormatCourseToLayout(symbolDB, activeCourseView, appearance, activeCourse, CourseLayer.MainCourse);

            if (showAllControls && !activeCourseDesignator.IsAllControls) {
                // Create the all controls view.
                CourseView allControlsView = CourseView.CreateFilteredAllControlsView(eventDB, new CourseDesignator[] { activeCourseDesignator }, allControlsFilter, 
                    new CourseViewOptions() { showNonDescriptionSpecials = false, showDescriptionSpecials = false });

                // Add it to the CourseLayout.
                activeCourse.SetLayerColor(CourseLayer.AllControls, NormalCourseAppearance.allControlsOcadId, NormalCourseAppearance.allControlsColorName,
                    NormalCourseAppearance.allControlsColorC, NormalCourseAppearance.allControlsColorM, NormalCourseAppearance.allControlsColorY, NormalCourseAppearance.allControlsColorK, purpleOverprint);
                CourseFormatter.FormatCourseToLayout(symbolDB, allControlsView, appearance, activeCourse, CourseLayer.AllControls);
            }

            if (extraCourses != null && extraCourses.Count > 0) {
                for (int i = 0; i < extraCourses.Count; ++i) {
                    Id<Course> courseId = extraCourses[i];
                    if (eventDB.IsCoursePresent(courseId)) {
                        AddExtraCourseToLayout(activeCourse, courseId, i % CourseLayout.EXTRACOURSECOUNT);
                    }
                }
            }
        }
Example #8
0
        // extraCourseIndex indicates the color/layer.
        private void AddExtraCourseToLayout(CourseLayout courseLayout, Id<Course> courseId, int extraCourseIndex)
        {
            if (extraCourseIndex >= CourseLayout.EXTRACOURSECOUNT)
                return;

            CourseAppearance appearance = controller.GetCourseAppearance();
            CourseLayer layer = CourseLayer.OtherCourse1 + extraCourseIndex;

            // Create the course view.
            CourseView courseView = CourseView.CreateCourseView(eventDB, new CourseDesignator(courseId),
                new CourseViewOptions() { showNonDescriptionSpecials = false, showDescriptionSpecials = false, showControlNumbers = false });

            // Add it to the CourseLayout.
            courseLayout.SetLayerColor(layer, (short) (NormalCourseAppearance.extraCourseOcadId + extraCourseIndex), 
                                              string.Format(NormalCourseAppearance.allControlsColorName, extraCourseIndex + 1),
                                              NormalCourseAppearance.extraCourseC[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseM[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseY[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseK[extraCourseIndex],
                                              false);

            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, courseLayout, layer,
                new CourseFormatterOptions() { showControlNumbers = false });
        }
Example #9
0
        // Get the area of the map we want to print, in map coordinates, and the print scale.
        // if the courseId is None, do all controls.
        // If asked for, crop to a single page size.
        RectangleF GetPrintAreaForCourse(CourseDesignator courseDesignator, out bool landscape, out PaperSize paperSize, out int margins, out float scaleRatio, out string description)
        {
            // Get the course view to get the scale ratio.
            CourseView courseView = CourseView.CreatePositioningCourseView(eventDB, courseDesignator);

            scaleRatio  = courseView.ScaleRatio;
            description = courseView.CourseFullName;

            RectangleF printRectangle = controller.GetCurrentPrintAreaRectangle(courseDesignator);
            PrintArea  printArea      = controller.GetCurrentPrintArea(courseDesignator);

            landscape = printArea.pageLandscape;
            paperSize = new PaperSize("", printArea.pageWidth, printArea.pageHeight);
            margins   = printArea.pageMargins;

            if (cropLargePrintArea)
            {
                // Crop the print area to a single page, portrait or landscape.
                // Try to keep CourseObjects in view as much as possible.
                CourseLayout layout = new CourseLayout();
                CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, 0);
                RectangleF courseObjectsArea = layout.BoundingRect();
                courseObjectsArea.Intersect(printRectangle);

                // We may need to crop the print area to fit.
                float      areaCovered;
                RectangleF printableArea    = GetPrintablePageArea(landscape, paperSize, margins);
                RectangleF croppedRectangle = CropPrintArea(printRectangle, courseObjectsArea, GetScaledPrintableSizeInMapUnits(printableArea, scaleRatio), out areaCovered);

                return(croppedRectangle);
            }
            else
            {
                return(printRectangle);
            }
        }
Example #10
0
        // The core printing routine. The origin of the graphics is the upper-left of the margins,
        // and the printArea in the size to draw into (in hundreths of an inch).
        protected override void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi)
        {
            CoursePage page = pages[pageNumber];

            // Get the course view for the course we are printing.
            CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator);

            // Get the correct purple color to print the course in.
            short ocadId;
            float purpleC, purpleM, purpleY, purpleK;
            bool  purpleOverprint;

            FindPurple.GetPurpleColor(mapDisplay, appearance, out ocadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint);

            // Create a course layout from the view.
            CourseLayout layout = new CourseLayout();

            layout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
            layout.SetLayerColor(CourseLayer.MainCourse, ocadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, purpleOverprint);
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, CourseLayer.MainCourse);

            // Set the course layout into the map display
            mapDisplay.SetCourse(layout);
            this.mapDisplay.SetPrintArea(null);

            // Collecting garbage should make out of memory less common.
            GC.Collect();

            if (graphicsTarget is GDIPlus_GraphicsTarget)
            {
                // We print to intermediate bands of bitmaps. This is the only way to get purple blending correct.
                // Other code ensure that if purple blending is on, we always take this code path.

                GDIPlus_GraphicsTarget gdiGraphicsTarget = ((GDIPlus_GraphicsTarget)graphicsTarget);
                Graphics g = gdiGraphicsTarget.Graphics;
                // Save and restore state so we can mess with stuff.
                GraphicsState graphicsState = g.Save();

                // Printing via a bitmap. Works best with some print drivers.
                dpi = AdjustDpi(dpi);

                const long        MAX_PIXELS_PER_BAND = 20000000; // 20M pixels = 60M bytes (3 bytes per pixel).
                List <CoursePage> bands = BandPageToLimitBitmapSize(page, dpi, MAX_PIXELS_PER_BAND);

                // Create the bitmap. Can do this once because each band is the same size.
                int    bitmapWidth  = (int)Math.Round(bands[0].printRectangle.Width * dpi / 100F);
                int    bitmapHeight = (int)Math.Round(bands[0].printRectangle.Height * dpi / 100F);
                Bitmap bitmap       = new Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                foreach (CoursePage band in bands)
                {
                    // Set the transform
                    Matrix transform = Geometry.CreateInvertedRectangleTransform(band.mapRectangle, new RectangleF(0, 0, bitmapWidth, bitmapHeight));
                    mapDisplay.Draw(bitmap, transform);

                    try {
                        // Draw the bitmap on the printer.
                        g.DrawImage(bitmap, band.printRectangle);
                    }
                    catch (Exception) { }
                }

                // restore state.
                g.Restore(graphicsState);
                bitmap.Dispose();
            }
            else
            {
                // Print directly. Used only when prerasterization is off.
                // Set the transform, and the clip.
                Matrix transform = Geometry.CreateInvertedRectangleTransform(page.mapRectangle, page.printRectangle);
                PushRectangleClip(graphicsTarget, page.printRectangle);
                graphicsTarget.PushTransform(transform);
                // Determine the resolution in map coordinates.
                Matrix inverseTransform = transform.Clone();
                inverseTransform.Invert();
                float minResolutionPage = 100F / dpi;
                float minResolutionMap  = Geometry.TransformDistance(minResolutionPage, inverseTransform);

                // And draw.
                mapDisplay.Draw(graphicsTarget, page.mapRectangle, minResolutionMap);

                graphicsTarget.PopTransform();
                graphicsTarget.PopClip();
            }
        }