// Format the given CourseView into a bunch of course objects, and add it to the given course Layout public RectangleF FormatCourseToLayout(SymbolDB symbolDB, CourseView courseViewAllVariations, CourseView specificVariation, CourseLayout courseLayout, CourseLayer layerAllVariations, CourseLayer layerSpecificVariation) { this.eventDB = courseViewAllVariations.EventDB; this.symbolDB = symbolDB; this.courseLayout = courseLayout; this.courseLayerAllVariationsAndParts = layerAllVariations; this.courseLayerSpecificVariation = layerSpecificVariation; this.controlViewsAllVariationsAndParts = courseViewAllVariations.ControlViews; this.controlViewsSpecificVariation = specificVariation.ControlViews; this.controlPositions = new ControlPosition[controlViewsAllVariationsAndParts.Count]; this.courseControlIdsSpecificVariation = QueryEvent.EnumCourseControlIds(eventDB, specificVariation.CourseDesignator).ToArray(); this.variationMap = QueryEvent.GetVariantCodeMapping(eventDB, courseViewAllVariations.CourseDesignator); SizeF totalAbstractSize = AssignControlPositions(0, controlViewsAllVariationsAndParts.Count, 0, 0); // Now create objects now that the positions have been created. scaleRatio = 1.0F; appearance = new CourseAppearance(); for (int index = 0; index < controlViewsAllVariationsAndParts.Count; ++index) { CreateObjectsForControlView(controlViewsAllVariationsAndParts[index], controlPositions[index]); } PointF bottomCenter = LocationFromAbstractPosition(0, 0); SizeF size = SizeFromAbstractSize(totalAbstractSize); RectangleF rect = new RectangleF(bottomCenter.X - size.Width / 2, bottomCenter.Y - size.Height, size.Width, size.Height); rect.Inflate(widthUnit, heightUnit); return rect; }
// Format the given CourseView into a bunch of course objects, and add it to the given course Layout public RectangleF FormatCourseToLayout(SymbolDB symbolDB, CourseView courseViewAllVariations, CourseView specificVariation, CourseLayout courseLayout, Id <CourseControl> ccSelection1, Id <CourseControl> ccSelection2, CourseLayer layerAllVariations, CourseLayer layerSpecificVariation) { this.eventDB = courseViewAllVariations.EventDB; this.symbolDB = symbolDB; this.courseLayout = courseLayout; this.courseLayerAllVariationsAndParts = layerAllVariations; this.courseLayerSpecificVariation = layerSpecificVariation; this.controlViewsAllVariationsAndParts = courseViewAllVariations.ControlViews; this.controlViewsSpecificVariation = specificVariation.ControlViews; this.controlPositions = new ControlPosition[controlViewsAllVariationsAndParts.Count]; this.courseControlIdsSpecificVariation = QueryEvent.EnumCourseControlIds(eventDB, specificVariation.CourseDesignator).ToArray(); this.courseControlIdSelection1 = ccSelection1; this.courseControlIdSelection2 = ccSelection2; this.variationMap = QueryEvent.GetVariantCodeMapping(eventDB, courseViewAllVariations.CourseDesignator); SizeF totalAbstractSize = AssignControlPositions(0, controlViewsAllVariationsAndParts.Count, 0, 0); // Now create objects now that the positions have been created. courseObjRatio = 1.0F; appearance = new CourseAppearance(); for (int index = 0; index < controlViewsAllVariationsAndParts.Count; ++index) { CreateObjectsForControlView(controlViewsAllVariationsAndParts[index], controlPositions[index]); } PointF bottomCenter = LocationFromAbstractPosition(0, 0); SizeF size = SizeFromAbstractSize(totalAbstractSize); RectangleF rect = new RectangleF(bottomCenter.X - size.Width / 2, bottomCenter.Y - size.Height, size.Width, size.Height); rect.Inflate(widthUnit, heightUnit); return(rect); }
public static readonly object KeyLayout = "LayoutKey"; // key to get the "layout" symdef. // Set the color of a particular layer. Layer 0 is black, layer 1 is the primary course, layer 2 all other controls, // and layers 3 and above for other courses. public void SetLayerColor(CourseLayer layer, short ocadColorId, string colorName, float colorC, float colorM, float colorY, float colorK, bool overprint) { this.ocadColorId[(int)layer] = ocadColorId; this.colorName[(int)layer] = colorName; this.colorC[(int)layer] = colorC; this.colorM[(int)layer] = colorM; this.colorY[(int)layer] = colorY; this.colorK[(int)layer] = colorK; this.colorOverprint[(int)layer] = overprint; }
void CheckHitTest(CourseLayout course, PointF point, CourseLayer layerFilter, Predicate <CourseObj> filter, string expectedObject) { CourseObj courseobj = course.HitTest(point, 0.1F, layerFilter, filter); if (courseobj == null) { Assert.IsNull(expectedObject); } else { Console.WriteLine(courseobj); Assert.AreEqual(expectedObject, courseobj.ToString()); } }
public override bool GetToolTip(Pane pane, PointF location, float pixelSize, out string tipText, out string titleText) { CourseLayout activeCourse; CourseView courseView = selectionMgr.ActiveCourseView; if (pane == Pane.Map) { activeCourse = controller.GetCourseLayout(); } else { activeCourse = controller.GetTopologyLayout(); } CourseObj touchedObject = null; for (CourseLayer layer = CourseLayer.MainCourse; layer <= CourseLayer.AllControls; ++layer) { if (touchedObject == null) { touchedObject = activeCourse.HitTest(location, pixelSize, layer, co => !(co is TopologyDropTargetCourseObj)); } } if (touchedObject != null) { TextPart[] textParts = SelectionDescriber.DescribeCourseObject(symbolDB, eventDB, touchedObject, courseView.ScaleRatio); if (textParts != null) { ConvertTextPartsToToolTip(textParts, out tipText, out titleText); return(true); } } tipText = titleText = ""; return(false); }
// 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 }); }
void CheckCourse(string testfileName, Id<Course> courseId, CourseLayer layer, string expected) { 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(testfileName)); eventDB.Validate(); // Create the course courseView = CourseView.CreateViewingCourseView(eventDB, new CourseDesignator(courseId)); course = new CourseLayout(); CourseFormatter.FormatCourseToLayout(symbolDB, courseView, defaultCourseAppearance, course, layer); // Dump it to a string. StringWriter writer = new StringWriter(); course.Dump(writer); // Check that the string is correct. string actual = writer.ToString(); if (expected != actual) { for (int i = 0; i < Math.Min(expected.Length, actual.Length); ++i) if (actual[i] != expected[i]) { Console.WriteLine("Difference at -->{0}", actual.Substring(i, 30)); break; } } Assert.AreEqual(expected, writer.ToString()); }
void CheckHitTest(CourseLayout course, PointF point, CourseLayer layerFilter, Predicate<CourseObj> filter, string expectedObject) { CourseObj courseobj = course.HitTest(point, 0.1F, layerFilter, filter); if (courseobj == null) { Assert.IsNull(expectedObject); } else { Console.WriteLine(courseobj); Assert.AreEqual(expectedObject, courseobj.ToString()); } }
// Check a point against a set of course objects. // The layerFilter, if >= 0, limits the objects consider to those in the given layer. // The filter, if non-null, is an additional filter (return true to consider) public static CourseObj HitTestCollection(IEnumerable <CourseObj> courseObjects, PointF point, float pixelSize, CourseLayer layerFilter, Predicate <CourseObj> filter) { // We need to hit within 3 pixels of an object to select it. double distanceLimit = pixelSize * 3; double bestDistance = distanceLimit; int bestPriority = -1; CourseObj bestObject = null; foreach (CourseObj courseObject in courseObjects) { if (layerFilter >= 0 && courseObject.layer != layerFilter) { continue; } if (filter != null && !filter(courseObject)) { continue; } double dist = courseObject.DistanceFromPoint(point); int priority = courseObject.SelectionPriority(); if (dist < distanceLimit) { // Could be selected. Check if other object is better. if (priority > bestPriority || (priority == bestPriority && dist < bestDistance)) { bestDistance = dist; bestObject = courseObject; bestPriority = priority; } } } return(bestObject); }
// Find a course object from a point, and a "pixelsize" that says how big one pixel is. // If no course object is hit, then we return null. // The layerFilter, if >= 0, limits the objects consider to those in the given layer. // The filter, if non-null, is an additional filter (return true to consider) public CourseObj HitTest(PointF point, float pixelSize, CourseLayer layerFilter, Predicate <CourseObj> filter) { return(HitTestCollection(this, point, pixelSize, layerFilter, filter)); }
// Create the course objects associated with this special. Assign the given layer to it. static CourseObj CreateSpecial(EventDB eventDB, CourseView courseView, float scaleRatio, CourseAppearance appearance, Id<Special> specialId, CourseLayer normalLayer) { Special special = eventDB.GetSpecial(specialId); CourseObj courseObj = null; switch (special.kind) { case SpecialKind.FirstAid: courseObj = new FirstAidCourseObj(specialId, scaleRatio, appearance, special.locations[0]); break; case SpecialKind.Water: courseObj = new WaterCourseObj(specialId, scaleRatio, appearance, special.locations[0]); break; case SpecialKind.OptCrossing: courseObj = new CrossingCourseObj(Id<ControlPoint>.None, Id<CourseControl>.None, specialId, scaleRatio, appearance, special.orientation, special.locations[0]); break; case SpecialKind.Forbidden: courseObj = new ForbiddenCourseObj(specialId, scaleRatio, appearance, special.locations[0]); break; case SpecialKind.RegMark: courseObj = new RegMarkCourseObj(specialId, scaleRatio, appearance, special.locations[0]); break; case SpecialKind.Boundary: courseObj = new BoundaryCourseObj(specialId, scaleRatio, appearance, new SymPath(special.locations)); break; case SpecialKind.Rectangle: courseObj = new RectSpecialCourseObj(specialId, appearance, special.color, special.lineKind, special.lineWidth, special.cornerRadius, special.gapSize, special.dashSize, Geometry.RectFromPoints(special.locations[0], special.locations[1])); break; case SpecialKind.Line: courseObj = new LineSpecialCourseObj(specialId, appearance, special.color, special.lineKind, special.lineWidth, special.gapSize, special.dashSize, new SymPath(special.locations)); break; case SpecialKind.OOB: courseObj = new OOBCourseObj(specialId, scaleRatio, appearance, special.locations); break; case SpecialKind.Dangerous: courseObj = new DangerousCourseObj(specialId, scaleRatio, appearance, special.locations); break; case SpecialKind.WhiteOut: courseObj = new WhiteOutCourseObj(specialId, scaleRatio, appearance, special.locations); break; case SpecialKind.Image: Special imageSpecial = eventDB.GetSpecial(specialId); courseObj = new ImageCourseObj(specialId, scaleRatio, appearance, special.locations, imageSpecial.text, imageSpecial.imageBitmap); break; case SpecialKind.Text: string text = ExpandText(eventDB, courseView, special.text); FontStyle fontStyle = Util.GetFontStyle(special.fontBold, special.fontItalic); RectangleF boundingRect = RectangleF.FromLTRB((float)Math.Min(special.locations[0].X, special.locations[1].X), (float)Math.Min(special.locations[0].Y, special.locations[1].Y), (float)Math.Max(special.locations[0].X, special.locations[1].X), (float)Math.Max(special.locations[0].Y, special.locations[1].Y)); courseObj = new BasicTextCourseObj(specialId, text, boundingRect, special.fontName, fontStyle, special.color); break; case SpecialKind.Descriptions: Debug.Fail("description specials should not be passed to this function"); return null; default: Debug.Fail("bad special kind"); return null; } courseObj.layer = normalLayer; return courseObj; }
// Create the course objects associated with this special. Assign the given layer to it. static CourseObj CreateDescriptionSpecial(EventDB eventDB, SymbolDB symbolDB, CourseView.DescriptionView descriptionView, CourseLayer layer) { Special special = eventDB.GetSpecial(descriptionView.SpecialId); Debug.Assert(special.kind == SpecialKind.Descriptions); DescriptionKind descKind; DescriptionLine[] description = GetCourseDescription(eventDB, symbolDB, descriptionView.CourseDesignator, out descKind); CourseObj courseObj = new DescriptionCourseObj(descriptionView.SpecialId, special.locations[0], (float)Geometry.Distance(special.locations[0], special.locations[1]), symbolDB, description, descKind, special.numColumns); courseObj.layer = layer; return courseObj; }
// Cut any overlapping legs in the given layer. private static void AutoCutLegs(EventDB eventDB, CourseAppearance appearance, CourseDesignator courseDesignator, CourseLayout courseLayout, CourseLayer layer) { if (appearance.autoLegGapSize <= 0) return; // No cutting requested. foreach (CourseObj courseObj in courseLayout) { if (courseObj.layer == layer && (courseObj is LegCourseObj || courseObj is FlaggedLegCourseObj)) AutoCutLeg(eventDB, appearance, courseDesignator, (LineCourseObj)courseObj, courseLayout); } }
// Cut any overlapping control circles in the given layer. private static void AutoCutCircles(CourseLayout courseLayout, CourseLayer layer) { foreach (CourseObj courseObj in courseLayout) { if (courseObj.layer == layer && (courseObj is ControlCourseObj || courseObj is FinishCourseObj)) AutoCutControl((PointCourseObj) courseObj, courseLayout); } }
// Format the given CourseView into a bunch of course objects, and add it to the given course Layout public static void FormatCourseToLayout(SymbolDB symbolDB, CourseView courseView, CourseAppearance appearance, CourseLayout courseLayout, CourseLayer layer) { EventDB eventDB = courseView.EventDB; CourseView.CourseViewKind kind = courseView.Kind; ControlLabelKind labelKind = courseView.ControlLabelKind; float scaleRatio = courseView.ScaleRatio; List<CourseView.ControlView> controlViews = courseView.ControlViews; CourseObj courseObj; // Go through all the specials in the view and process them to create course objects foreach(Id<Special> specialId in courseView.SpecialIds) { courseObj = CreateSpecial(eventDB, courseView, scaleRatio, appearance, specialId, layer); if (courseObj != null) courseLayout.AddCourseObject(courseObj); } // Go through all the descriptions in the view and process them to create course objects foreach (CourseView.DescriptionView descriptionView in courseView.DescriptionViews) { // The layer depends on "descriptions in purple" setting in the course appearance. courseObj = CreateDescriptionSpecial(eventDB, symbolDB, descriptionView, appearance.descriptionsPurple ? layer : CourseLayer.Descriptions); if (courseObj != null) courseLayout.AddCourseObject(courseObj); } // Go through all the controls in the view and process them to create controls and legs. for (int controlIndex = 0; controlIndex < controlViews.Count; ++controlIndex) { CourseView.ControlView controlView = controlViews[controlIndex]; if (!controlView.hiddenControl) { // Get the angles of the legs into and out of this control, in radians. double angleOut = ComputeAngleOut(eventDB, courseView, controlIndex); // Get the normal course object associated with this control. courseObj = CreateCourseObject(eventDB, scaleRatio, appearance, courseView.PrintScale, controlView, angleOut); if (courseObj != null) { courseObj.layer = layer; courseLayout.AddCourseObject(courseObj); } // If this course-control indicates custom placement, place the number/code now (so it influences auto-placed numbers). if (CustomPlaceNumber(eventDB, controlView)) { if (kind == CourseView.CourseViewKind.AllControls) courseObj = CreateCode(eventDB, scaleRatio, appearance, controlView, courseLayout); else if (kind == CourseView.CourseViewKind.AllVariations) courseObj = CreateControlNumber(eventDB, scaleRatio, appearance, ControlLabelKind.Code, controlView, courseView, courseLayout); else courseObj = CreateControlNumber(eventDB, scaleRatio, appearance, labelKind, controlView, courseView, courseLayout); if (courseObj != null) { courseObj.layer = layer; courseLayout.AddCourseObject(courseObj); } } } if (kind == CourseView.CourseViewKind.Normal || kind == CourseView.CourseViewKind.AllVariations) { // Get the object(s) associated with the leg(s) to the next control. if (controlView.legTo != null) { for (int leg = 0; leg < controlView.legTo.Length; ++leg) { CourseObj[] courseObjs = CreateLeg(eventDB, scaleRatio, appearance, controlView.courseControlIds[leg], controlView, controlViews[controlView.legTo[leg]], controlView.legId[leg]); if (courseObjs != null) { foreach (CourseObj o in courseObjs) { o.layer = layer; courseLayout.AddCourseObject(o); } } } } } } // Add any additional controls foreach (Id<CourseControl> extraCourseControl in courseView.ExtraCourseControls) { courseLayout.AddCourseObject(CreateCourseObject(eventDB, scaleRatio, appearance, courseView.PrintScale, eventDB.GetCourseControl(extraCourseControl).control, extraCourseControl, double.NaN)); } // No go through each control again and add an automatically placed number/code to each. We do this last so that the placement // of all fixed-position objects influences the auto-positioned numbers so that they don't interfere. for (int controlIndex = 0; controlIndex < controlViews.Count; ++controlIndex) { CourseView.ControlView controlView = controlViews[controlIndex]; // Only place numbers WITHOUT custom number placement. Those with custom placement were done previously above. if (!controlView.hiddenControl && ! CustomPlaceNumber(eventDB, controlView)) { if (kind == CourseView.CourseViewKind.AllControls) courseObj = CreateCode(eventDB, scaleRatio, appearance, controlView, courseLayout); else if (kind == CourseView.CourseViewKind.AllVariations) courseObj = CreateControlNumber(eventDB, scaleRatio, appearance, ControlLabelKind.Code, controlView, courseView, courseLayout); else courseObj = CreateControlNumber(eventDB, scaleRatio, appearance, labelKind, controlView, courseView, courseLayout); if (courseObj != null) { courseObj.layer = layer; courseLayout.AddCourseObject(courseObj); } } } // Automatically add cuts to close control circles in the layout. if (courseView.Kind != CourseView.CourseViewKind.AllControls) { AutoCutCircles(courseLayout, layer); AutoCutLegs(eventDB, appearance, courseView.CourseDesignator, courseLayout, layer); } }