public OcadCreation(SymbolDB symbolDB, EventDB eventDB, Controller controller, CourseAppearance courseAppearance, OcadCreationSettings creationSettings) { this.symbolDB = symbolDB; this.eventDB = eventDB; this.controller = controller; this.courseAppearance = courseAppearance; this.creationSettings = creationSettings; }
public AddControlMode(Controller controller, SelectionMgr selectionMgr, UndoMgr undoMgr, EventDB eventDB, SymbolDB symbolDB, bool allControls, ControlPointKind controlKind, bool exchangeAtControl) { this.controller = controller; this.selectionMgr = selectionMgr; this.undoMgr = undoMgr; this.eventDB = eventDB; this.symbolDB = symbolDB; this.allControls = allControls; this.controlKind = controlKind; this.exchangeAtControl = exchangeAtControl; this.scaleRatio = selectionMgr.ActiveCourseView.ScaleRatio; this.appearance = controller.GetCourseAppearance(); }
// Create a single object associated with the leg from courseControlId1 to courseControlId2. Does not consider // flagging (but does consider bends and gaps.) Used for highlighting on the map. public static CourseObj CreateSimpleLeg(EventDB eventDB, float scaleRatio, CourseAppearance appearance, Id<CourseControl> courseControlId1, Id<CourseControl> courseControlId2) { Id<ControlPoint> controlId1 = eventDB.GetCourseControl(courseControlId1).control; Id<ControlPoint> controlId2 = eventDB.GetCourseControl(courseControlId2).control; ControlPoint control1 = eventDB.GetControl(controlId1); ControlPoint control2 = eventDB.GetControl(controlId2); LegGap[] gaps; SymPath legPath = GetLegPath(eventDB, control1.location, control1.kind, controlId1, control2.location, control2.kind, controlId2, scaleRatio, appearance, out gaps); if (legPath == null) return null; return new LegCourseObj(controlId1, courseControlId1, courseControlId2, scaleRatio, appearance, legPath, gaps); }
public LinePropertiesDialog(string dialogTitle, string usageText, CmykColor purpleColor, CourseAppearance appearance) { InitializeComponent(); this.appearance = appearance; if (!appearance.useDefaultPurple) { purpleColor = CmykColor.FromCmyk(appearance.purpleC, appearance.purpleM, appearance.purpleY, appearance.purpleK); } this.purpleColor = SwopColorConverter.CmykToRgbColor(purpleColor); colorChooser = new SpecialColorChooser(comboBoxColor, buttonChangeColor, purpleColor); colorChooser.ColorChanged += colorChooser_ColorChanged; LineKind = PurplePen.LineKind.Single; this.Text = dialogTitle; usageLabel.Text = usageText; }
// mapDisplay is a MapDisplay that contains the correct map. All other features of the map display need to be customized. public CoursePrinting(EventDB eventDB, SymbolDB symbolDB, Controller controller, MapDisplay mapDisplay, CoursePrintSettings coursePrintSettings, CourseAppearance appearance) : base(QueryEvent.GetEventTitle(eventDB, " "), controller, coursePrintSettings.PageSettings, coursePrintSettings.PrintingColorModel) { this.eventDB = eventDB; this.symbolDB = symbolDB; this.controller = controller; this.mapDisplay = mapDisplay; this.coursePrintSettings = coursePrintSettings; this.appearance = appearance; // Set default features for printing. mapDisplay.MapIntensity = 1.0F; mapDisplay.AntiAlias = false; mapDisplay.Printing = true; mapDisplay.ColorModel = base.colorModel; }
SymPathWithHoles path; // closed path with the area to fill #endregion Fields #region Constructors protected AreaCourseObj(Id<ControlPoint> controlId, Id<CourseControl> courseControlId, Id<Special> specialId, float scaleRatio, CourseAppearance appearance, PointF[] pts) : base(controlId, courseControlId, specialId, scaleRatio, appearance) { bool lastPtSynthesized = false; if (pts[pts.Length - 1] != pts[0]) { // If needed, synthesize a final point to close the path. PointF[] newPts = new PointF[pts.Length + 1]; Array.Copy(pts, newPts, pts.Length); newPts[pts.Length] = pts[0]; pts = newPts; lastPtSynthesized = true; } PointKind[] kinds = new PointKind[pts.Length]; for (int i = 0; i < kinds.Length; ++i) kinds[i] = PointKind.Normal; this.path = new SymPathWithHoles(new SymPath(pts, kinds, null, lastPtSynthesized), null); }
// mapDisplay is a MapDisplay that contains the correct map. All other features of the map display need to be customized. public CoursePdf(EventDB eventDB, SymbolDB symbolDB, Controller controller, MapDisplay mapDisplay, CoursePdfSettings coursePdfSettings, CourseAppearance appearance) { this.eventDB = eventDB; this.symbolDB = symbolDB; this.controller = controller; this.mapDisplay = mapDisplay; this.coursePdfSettings = coursePdfSettings; this.appearance = appearance; // Set default features for printing. mapDisplay.MapIntensity = 1.0F; mapDisplay.AntiAlias = false; mapDisplay.Printing = true; mapDisplay.ColorModel = coursePdfSettings.ColorModel; mapBounds = mapDisplay.MapBounds; if (mapDisplay.MapType == MapType.PDF) { // For PDF maps, we remove the PDF map from the MapDisplay and add it in separately. sourcePdfMapFileName = mapDisplay.FileName; } }
// Get the radius of where the leg should start from a control point of a given kind. private static double GetLegRadius(ControlPointKind controlKind, float scaleRatio, CourseAppearance appearance) { switch (controlKind) { case ControlPointKind.CrossingPoint: return scaleRatio * NormalCourseAppearance.crossingRadius * appearance.controlCircleSize; case ControlPointKind.Normal: return scaleRatio * ((NormalCourseAppearance.controlOutsideDiameter * appearance.controlCircleSize / 2F) - (NormalCourseAppearance.lineThickness * appearance.lineWidth / 2F)); case ControlPointKind.Finish: return scaleRatio * ((NormalCourseAppearance.finishOutsideDiameter * appearance.controlCircleSize / 2F) - (NormalCourseAppearance.lineThickness * appearance.lineWidth / 2F)); case ControlPointKind.Start: case ControlPointKind.MapExchange: return scaleRatio * NormalCourseAppearance.startRadius * appearance.controlCircleSize; case ControlPointKind.None: return 0; default: Debug.Fail("Bad kind"); return 0; } }
// Cut the leg "legObj" with respect to "otherObj", if they overlap private static void CutLegWithRespectTo(EventDB eventDB, CourseAppearance appearance, CourseDesignator courseDesignator, LineCourseObj legObj, PointCourseObj otherObj) { float radiusOther = otherObj.ApparentRadius; PointF nearestPointOnLeg; float distance = legObj.path.DistanceFromPoint(otherObj.location, out nearestPointOnLeg); if (distance < radiusOther && Geometry.Distance(nearestPointOnLeg, legObj.path.FirstPoint) > 0.5 && Geometry.Distance(nearestPointOnLeg, legObj.path.LastPoint) > 0.5) { float gapRadius = (float) Math.Sqrt(radiusOther * radiusOther - distance * distance); // pythagorean theorem. gapRadius += appearance.autoLegGapSize / 2; CutLegAtPoint(legObj, nearestPointOnLeg, gapRadius); } }
static Brush highlightBrush; // brush used to draw highlights. #endregion Fields #region Constructors protected CourseObj(Id<ControlPoint> controlId, Id<CourseControl> courseControlId, Id<Special> specialId, float scaleRatio, CourseAppearance appearance) { this.controlId = controlId; this.courseControlId = courseControlId; this.specialId = specialId; this.scaleRatio = scaleRatio; this.appearance = appearance; }
public AddLineAreaSpecialMode(Controller controller, SelectionMgr selectionMgr, UndoMgr undoMgr, EventDB eventDB, Func<PointF[], Id<Special>> createObject, bool isArea) { this.controller = controller; this.selectionMgr = selectionMgr; this.undoMgr = undoMgr; this.eventDB = eventDB; this.createObject = createObject; this.isArea = isArea; this.scaleRatio = selectionMgr.ActiveCourseView.ScaleRatio; this.appearance = controller.GetCourseAppearance(); }
// Create highlights to and from a point to course controls. If controlDrag is set (optional), it is // used to get the correct bends for legs. // Static because it is used from DragControlMode also. public static CourseObj[] CreateLegHighlights(EventDB eventDB, PointF newPoint, Id<ControlPoint>controlDrag, ControlPointKind controlKind, Id<CourseControl> courseControlId1, Id<CourseControl> courseControlId2, float scaleRatio, CourseAppearance appearance) { List<CourseObj> highlights = new List<CourseObj>(); if (courseControlId1.IsNotNone) { Id<ControlPoint> controlId1 = eventDB.GetCourseControl(courseControlId1).control; ControlPoint control1 = eventDB.GetControl(controlId1); LegCourseObj highlight = CreateLegHighlight(eventDB, control1.location, control1.kind, controlId1, newPoint, controlKind, controlDrag, scaleRatio, appearance); if (highlight != null) highlights.Add(highlight); } if (courseControlId2.IsNotNone) { Id<ControlPoint> controlId2 = eventDB.GetCourseControl(courseControlId2).control; ControlPoint control2 = eventDB.GetControl(controlId2); LegCourseObj highlight = CreateLegHighlight(eventDB, newPoint, controlKind, controlDrag, control2.location, control2.kind, controlId2, scaleRatio, appearance); if (highlight != null) highlights.Add(highlight); } return highlights.ToArray(); }
// Create the object associated with the control/start/finish etc with this control view. // AngleOut is the direction IN RADIANs leaving the control. static CourseObj CreateCourseObject(EventDB eventDB, float scaleRatio, CourseAppearance appearance, float printScale, CourseView.ControlView controlView, double angleOut) { return CreateCourseObject(eventDB, scaleRatio, appearance, printScale, controlView.controlId, controlView.courseControlIds[0], angleOut); }
// Create the control number text object, avoiding existing objects on the map. This can be in the form of a sequence number, code, or both. private static CourseObj CreateControlNumber(EventDB eventDB, float scaleRatio, CourseAppearance appearance, ControlLabelKind labelKind, CourseView.ControlView controlView, CourseView courseView, IEnumerable<CourseObj> existingObjects) { ControlPoint control = eventDB.GetControl(controlView.controlId); CourseControl courseControl = eventDB.GetCourseControl(controlView.courseControlIds[0]); PointF controlLocation = control.location; PointF textCenterLocation; string text; if (control.kind == ControlPointKind.Normal) { text = GetControlLabelText(eventDB, labelKind, controlView, courseView); // Figure out where the control number goes. if (courseControl.customNumberPlacement) { textCenterLocation = new PointF(controlLocation.X + courseControl.numberDeltaX, controlLocation.Y + courseControl.numberDeltaY); } else { FontDesc fontDesc = appearance.numberBold ? NormalCourseAppearance.controlNumberFont : NormalCourseAppearance.controlNumberFontBold; textCenterLocation = GetTextLocation(controlLocation, (NormalCourseAppearance.controlOutsideDiameter / 2F + NormalCourseAppearance.controlNumberCircleDistance) * scaleRatio * appearance.controlCircleSize, text, fontDesc, scaleRatio * appearance.numberHeight, existingObjects); } return new ControlNumberCourseObj(controlView.controlId, controlView.courseControlIds[0], scaleRatio, appearance, text, textCenterLocation); } else { // Only normal controls have numbers. return null; } }
// Create the control code text object, avoiding existing objects on the map. private static CourseObj CreateCode(EventDB eventDB, float scaleRatio, CourseAppearance appearance, CourseView.ControlView controlView, IEnumerable<CourseObj> existingObjects) { ControlPoint control = eventDB.GetControl(controlView.controlId); CourseControl courseControl = controlView.courseControlIds[0].IsNotNone ? eventDB.GetCourseControl(controlView.courseControlIds[0]) : null; PointF controlLocation = control.location; string text; PointF textCenterLocation; float distanceFromCenter = (NormalCourseAppearance.controlOutsideDiameter / 2F + NormalCourseAppearance.codeCircleDistance) * scaleRatio * appearance.controlCircleSize; if (control.kind == ControlPointKind.Normal) { text = control.code; if (courseControl != null && courseControl.customNumberPlacement) { textCenterLocation = new PointF(controlLocation.X + courseControl.numberDeltaX, controlLocation.Y + courseControl.numberDeltaY); } else if (courseControl == null && control.customCodeLocation) { textCenterLocation = GetRectangleCenter(controlLocation, distanceFromCenter, (float) (control.codeLocationAngle * Math.PI / 180F), GetTextSize(text, NormalCourseAppearance.controlCodeFont, scaleRatio)); } else { textCenterLocation = GetTextLocation(controlLocation, distanceFromCenter, text, NormalCourseAppearance.controlCodeFont, scaleRatio * appearance.numberHeight, existingObjects); } return new CodeCourseObj(controlView.controlId, controlView.courseControlIds[0], scaleRatio, appearance, text, textCenterLocation); } else { // Only normal controls get codes. return null; } }
// 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); } }
// Check this leg and add cuts to it if needed. private static void AutoCutLeg(EventDB eventDB, CourseAppearance appearance, CourseDesignator courseDesignator, LineCourseObj legObj, CourseLayout courseLayout) { foreach (CourseObj courseObj in courseLayout) { if (courseObj != legObj && courseObj.layer == legObj.layer && (courseObj is LegCourseObj || courseObj is FlaggedLegCourseObj)) CutLegWithRespectTo(eventDB, appearance, courseDesignator, legObj, (LineCourseObj)courseObj); if (courseObj != legObj && courseObj.layer == legObj.layer && courseObj is PointCourseObj) CutLegWithRespectTo(eventDB, appearance, courseDesignator, legObj, (PointCourseObj)courseObj); } }
// Create a path from pt1 to pt2, with a radius aroudn the points correct for the given control kind. If the leg would // be of zero length, return null. The controlIds for the start and end points are optional -- if supplied, they are used // to deal with bends and gaps. If either is None, then the legs don't use bends or gaps. Returns the gaps to used // with the radius subtracted from them. public static SymPath GetLegPath(EventDB eventDB, PointF pt1, ControlPointKind kind1, Id<ControlPoint> controlId1, PointF pt2, ControlPointKind kind2, Id<ControlPoint> controlId2, float scaleRatio, CourseAppearance appearance, out LegGap[] gaps) { PointF[] bends = null; gaps = null; // Get bends and gaps if controls were supplied. if (controlId1.IsNotNone && controlId2.IsNotNone) { Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2); Leg leg = (legId.IsNotNone) ? eventDB.GetLeg(legId) : null; // Get the path of the line. if (leg != null) { bends = leg.bends; gaps = QueryEvent.GetLegGaps(eventDB, controlId1, controlId2); } } return GetLegPath(pt1, GetLegRadius(kind1, scaleRatio, appearance), pt2, GetLegRadius(kind2, scaleRatio, appearance), bends, gaps); }
// 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); } }
static CourseObj CreateCourseObject(EventDB eventDB, float scaleRatio, CourseAppearance appearance, float printScale, Id<ControlPoint> controlId, Id<CourseControl> courseControlId, double angleOut) { ControlPoint control = eventDB.GetControl(controlId); CircleGap[] gaps = QueryEvent.GetControlGaps(eventDB, controlId, printScale); CourseObj courseObj = null; switch (control.kind) { case ControlPointKind.Start: case ControlPointKind.MapExchange: courseObj = new StartCourseObj(controlId, courseControlId, scaleRatio, appearance, double.IsNaN(angleOut) ? 0 : (float)Geometry.RadiansToDegrees(angleOut), control.location, CrossHairOptions.HighlightCrossHair); break; case ControlPointKind.Finish: courseObj = new FinishCourseObj(controlId, courseControlId, scaleRatio, appearance, gaps, control.location, CrossHairOptions.HighlightCrossHair); break; case ControlPointKind.Normal: courseObj = new ControlCourseObj(controlId, courseControlId, scaleRatio, appearance, gaps, control.location); break; case ControlPointKind.CrossingPoint: courseObj = new CrossingCourseObj(controlId, courseControlId, Id<Special>.None, scaleRatio, appearance, control.orientation, control.location); break; default: Debug.Fail("bad control kind"); return null; } return courseObj; }
// Get the purple color to use for display, taking into account the user preferences in courseAppearance, the map loaded into the mapDisplay, // and the default purple if none of those provide a color. MapDisplay and courseAppearance can be null, in which case they won't be used. public static void GetPurpleColor(MapDisplay mapDisplay, CourseAppearance courseAppearance, out short ocadId, out float cyan, out float magenta, out float yellow, out float black, out bool overprint) { overprint = (courseAppearance == null) ? true : courseAppearance.purpleColorBlend; if (courseAppearance != null && !courseAppearance.useDefaultPurple) { // Use the purple from the course display. cyan = courseAppearance.purpleC; magenta = courseAppearance.purpleM; yellow = courseAppearance.purpleY; black = courseAppearance.purpleK; ocadId = NormalCourseAppearance.courseOcadId; return; } else if (mapDisplay != null && FindPurpleColor(mapDisplay.GetMapColors(), out ocadId, out cyan, out magenta, out yellow, out black)) { // FindPurpleColor found a purple to use. return; } else { // Use the program default. ocadId = NormalCourseAppearance.courseOcadId; cyan = NormalCourseAppearance.courseColorC; magenta = NormalCourseAppearance.courseColorM; yellow = NormalCourseAppearance.courseColorY; black = NormalCourseAppearance.courseColorK; return; } }
// 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; }
// 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 scaleRatio, CourseAppearance appearance) { LegGap[] gaps; SymPath path = CourseFormatter.GetLegPath(eventDB, pt1, kind1, controlId1, pt2, kind2, controlId2, scaleRatio, appearance, out gaps); if (path != null) return new LegCourseObj(controlId1, Id<CourseControl>.None, Id<CourseControl>.None, scaleRatio, appearance, path, null); // We never display the gaps, because it looks dumb. else return null; }
public ControlNumberCourseObj(Id<ControlPoint> controlId, Id<CourseControl> courseControlId, float scaleRatio, CourseAppearance appearance, string text, PointF centerPoint) : base(controlId, courseControlId, Id<Special>.None, text, centerPoint, NormalCourseAppearance.controlNumberFont.Name, appearance.numberBold ? NormalCourseAppearance.controlNumberFontBold.Style : NormalCourseAppearance.controlNumberFont.Style, SpecialColor.Purple, NormalCourseAppearance.controlNumberFont.EmHeight * scaleRatio * appearance.numberHeight, scaleRatio * appearance.numberOutlineWidth) { // Update the top left coord so the text is centered on centerPoint. this.centerPoint = centerPoint; topLeft = new PointF(centerPoint.X - size.Width / 2, centerPoint.Y + size.Height / 2); }
public AddPointSpecialMode(Controller controller, SelectionMgr selectionMgr, UndoMgr undoMgr, EventDB eventDB, SpecialKind specialKind) { this.controller = controller; this.selectionMgr = selectionMgr; this.undoMgr = undoMgr; this.eventDB = eventDB; this.specialKind = specialKind; this.scaleRatio = selectionMgr.ActiveCourseView.ScaleRatio; this.appearance = controller.GetCourseAppearance(); }
// Cut the leg "legObj" with respect to "otherObj", if they intersect private static void CutLegWithRespectTo(EventDB eventDB, CourseAppearance appearance, CourseDesignator courseDesignator, LineCourseObj legObj, LineCourseObj otherObj) { PointF[] intersectionPoints; if (legObj.path.Intersects(otherObj.path, out intersectionPoints) && intersectionPoints != null) { // The other line intersections this one. Only the later leg is split. if (QueryEvent.DoesCourseControlPrecede(eventDB, courseDesignator, otherObj.courseControlId, legObj.courseControlId)) { foreach (PointF intersectionPoint in intersectionPoints) { float gapRadius = appearance.autoLegGapSize / 2; CutLegAtPoint(legObj, intersectionPoint, gapRadius); } } } }
// Create the objects associated with the leg from controlView1 to controlView2. Could be multiple because // a leg may be partly flagged, and so forth. Gaps do not create separate course objects. private static CourseObj[] CreateLeg(EventDB eventDB, float scaleRatio, CourseAppearance appearance, Id<CourseControl> courseControlId1, CourseView.ControlView controlView1, CourseView.ControlView controlView2, Id<Leg> legId) { ControlPoint control1 = eventDB.GetControl(controlView1.controlId); ControlPoint control2 = eventDB.GetControl(controlView2.controlId); Leg leg = (legId.IsNotNone) ? eventDB.GetLeg(legId) : null; List<SymPath> paths = new List<SymPath>(); // paths for each segment of the leg. List<LegGap[]> gapsList = new List<LegGap[]>(); // gaps for each segment of the leg. List<bool> isFlagged = new List<bool>(); // indicates if each segment is flagged or not. LegGap[] gaps; // What kind of gaps are present? Null array if none // Get the path of the line, and the gaps. SymPath legPath = GetLegPath(eventDB, control1.location, controlView1.hiddenControl ? ControlPointKind.None : control1.kind, controlView1.controlId, control2.location, controlView2.hiddenControl ? ControlPointKind.None : control2.kind, controlView2.controlId, scaleRatio, appearance, out gaps); if (legPath == null) return null; // What kind of flagging does this leg have (none/full/begin/end)? FlaggingKind flagging = QueryEvent.GetLegFlagging(eventDB, controlView1.controlId, controlView2.controlId, legId); // Based on flagging kind, set up the paths/isFlagged lists. Add in gaps as part of it. if (flagging == FlaggingKind.Begin || flagging == FlaggingKind.End) { // Flagging is partial. We need to split the path into two. SymPath beginPath, endPath; legPath.Split(leg.flagStartStop, out beginPath, out endPath); paths.Add(beginPath); gapsList.Add(gaps); isFlagged.Add(flagging == FlaggingKind.Begin); // Update gaps for the end part. if (gaps != null) { gaps = (LegGap[]) gaps.Clone(); for (int i = 0; i < gaps.Length; ++i) gaps[i].distanceFromStart -= beginPath.Length; } paths.Add(endPath); gapsList.Add(gaps); isFlagged.Add(flagging == FlaggingKind.End); } else { // flagging is not partial. A single path is OK. paths.Add(legPath); gapsList.Add(gaps); isFlagged.Add(flagging == FlaggingKind.All); } // Create course objects for this leg from the paths/isFlagged lists. CourseObj[] objs = new CourseObj[paths.Count]; for (int i = 0; i < paths.Count; ++i) { if (isFlagged[i]) objs[i] = new FlaggedLegCourseObj(controlView1.controlId, courseControlId1, controlView2.courseControlIds[0], scaleRatio, appearance, paths[i], gapsList[i]); else objs[i] = new LegCourseObj(controlView1.controlId, courseControlId1, controlView2.courseControlIds[0], scaleRatio, appearance, paths[i], gapsList[i]); } return objs; }
public CrossingCourseObj(Id<ControlPoint> controlId, Id<CourseControl> courseControlId, Id<Special> specialId, float scaleRatio, CourseAppearance appearance, float orientation, PointF location) : base(controlId, courseControlId, specialId, scaleRatio, appearance, null, orientation, 1.72F, location) { }
// mapDisplay is a MapDisplay that contains the correct map. All other features of the map display need to be customized. public CoursePageLayout(EventDB eventDB, SymbolDB symbolDB, Controller controller, CourseAppearance appearance, bool cropLargePrintArea) { this.eventDB = eventDB; this.symbolDB = symbolDB; this.controller = controller; this.appearance = appearance; this.cropLargePrintArea = cropLargePrintArea; }
// 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; }