GetLeg() 공개 메소드

public GetLeg ( Id legId ) : Leg
legId Id
리턴 Leg
예제 #1
0
        // Get the angle from the given control index to the next control.
        public static double ComputeAngleOut(EventDB eventDB, CourseView courseView, int controlIndex)
        {
            PointF pt1 = eventDB.GetControl(courseView.ControlViews[controlIndex].controlId).location;

            // Get index of next control.
            int nextControlIndex = courseView.GetNextControl(controlIndex);
            if (nextControlIndex < 0)
                return double.NaN;

            // By default, the location of the next control is the direction.
            PointF pt2 = eventDB.GetControl(courseView.ControlViews[nextControlIndex].controlId).location;

            // If there is a custom leg, then use the location of the first bend instead.
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, courseView.ControlViews[controlIndex].controlId, courseView.ControlViews[nextControlIndex].controlId);
            if (legId.IsNotNone) {
                Leg leg = eventDB.GetLeg(legId);
                if (leg.bends != null && leg.bends.Length > 0)
                    pt2 = leg.bends[0];
            }

            return Math.Atan2(pt2.Y - pt1.Y, pt2.X - pt1.X);
        }
예제 #2
0
        // Find the SymPath of the path between controls, taking any bends into account. If no bends, the path is just the
        // simple path between the controls.
        public static SymPath GetLegPath(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, Id<Leg> legId)
        {
            PointF location1 = eventDB.GetControl(controlId1).location;
            PointF location2 = eventDB.GetControl(controlId2).location;

            if (legId.IsNotNone) {
                Leg leg = eventDB.GetLeg(legId);
                Debug.Assert(leg.controlId1 == controlId1 && leg.controlId2 == controlId2);

                if (leg.bends != null) {
                    List<PointF> points = new List<PointF>();
                    points.Add(location1);
                    points.AddRange(leg.bends);
                    points.Add(location2);
                    return new SymPath(points.ToArray());
                }
            }

            // No bends.
            return new SymPath(new PointF[] { location1, location2 });
        }
예제 #3
0
 // Find the start/stop gaps fort he leg from controlId1 to controlsId2. The legId, if not none, must be the correct leg id.
 public static LegGap[] GetLegGaps(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, Id<Leg> legId)
 {
     if (legId.IsNotNone) {
         Leg leg = eventDB.GetLeg(legId);
         Debug.Assert(leg.controlId1 == controlId1 && leg.controlId2 == controlId2);
         return (leg.gaps == null) ? null : (LegGap[])leg.gaps.Clone();
     }
     else {
         return null;
     }
 }
예제 #4
0
        // Find the kind of flagging for the leg from controlId1 to controlIs2. The legId, if not none, must be the correct leg id.
        public static FlaggingKind GetLegFlagging(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, Id<Leg> legId)
        {
            FlaggingKind flagging = FlaggingKind.None;
            if (legId.IsNotNone) {
                Leg leg = eventDB.GetLeg(legId);
                Debug.Assert(leg.controlId1 == controlId1 && leg.controlId2 == controlId2);
                flagging = leg.flagging;
            }

            ControlPoint control2 = eventDB.GetControl(controlId2);
            if (control2.kind == ControlPointKind.Finish && control2.symbolIds[0] == "14.1")
                flagging = FlaggingKind.All;
            if (control2.kind == ControlPointKind.MapExchange)
                flagging = FlaggingKind.All;

            return flagging;
        }
예제 #5
0
        // Find a leg object, if one exists, between the two controls.
        public static Id<Leg> FindLeg(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2)
        {
            // Go through all the legs to find one that matches.
            foreach (Id<Leg> legId in eventDB.AllLegIds) {
                Leg leg = eventDB.GetLeg(legId);
                if (leg.controlId1 == controlId1 && leg.controlId2 == controlId2) {
                    return legId;
                }
            }

            // Didn't find it.
            return Id<Leg>.None;
        }
예제 #6
0
        // Similar to ComputeLegLength. However, if the leg is flagged partially, only the length of the flagged portion is returned.
        // Note: if the flagging is NONE, this still returns the length of the whole leg!
        public static float ComputeFlaggedLegLength(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, Id<Leg> legId)
        {
            PointF location1 = eventDB.GetControl(controlId1).location;
            PointF location2 = eventDB.GetControl(controlId2).location;
            PointF[] bends = null;
            Leg leg = null;

            if (legId.IsNotNone) {
                leg = eventDB.GetLeg(legId);
                Debug.Assert(leg.controlId1 == controlId1 && leg.controlId2 == controlId2);
                bends = leg.bends;
            }

            if (bends == null) {
                return (float)((eventDB.GetEvent().mapScale * Geometry.Distance(location1, location2)) / 1000.0);
            }
            else {
                List<PointF> points = new List<PointF>();
                int bendIndexStart, bendIndexStop;

                points.Add(location1);
                points.AddRange(bends);
                points.Add(location2);

                // Which part is flagged?
                if (leg.flagging == FlaggingKind.Begin) {
                    bendIndexStart = 0; bendIndexStop = points.IndexOf(leg.flagStartStop);
                }
                else if (leg.flagging == FlaggingKind.End) {
                    bendIndexStart = points.IndexOf(leg.flagStartStop); bendIndexStop = points.Count - 1;
                }
                else {
                    bendIndexStart = 0; bendIndexStop = points.Count - 1;
                }

                double dist = 0;

                for (int i = bendIndexStart + 1; i <= bendIndexStop; ++i)
                    dist += Geometry.Distance(points[i - 1], points[i]);

                return (float)((eventDB.GetEvent().mapScale * dist) / 1000.0);
            }
        }
예제 #7
0
        // 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;
        }
예제 #8
0
        // 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);
        }
예제 #9
0
        // Change the flagging associated with a leg. If changing to Begin/End flagging, then a bend will be introduced if no bends currently exist
        // in the leg. If the leg ends in the finish, the finish symbol may be changed to match if appropriate.
        public static void ChangeFlagging(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, FlaggingKind flagging)
        {
            ControlPoint control1 = eventDB.GetControl(controlId1);
            ControlPoint control2 = eventDB.GetControl(controlId2);

            if (control2.kind == ControlPointKind.Finish && flagging == FlaggingKind.All) {
                // If the leg ends in the finish control, we can set all flagging by just changing the finish control symbol.
                ChangeDescriptionSymbol(eventDB, controlId2, 0, "14.1");
                return;
            }

            // We need a leg object. Create a new one or get the existing one.
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2);
            Leg leg;
            if (legId.IsNone)
                leg = new Leg(controlId1, controlId2);
            else
                leg = (Leg) eventDB.GetLeg(legId).Clone();

            // Set the flagging kind.
            leg.flagging = flagging;

            if (flagging == FlaggingKind.Begin || flagging == FlaggingKind.End) {
                // These kinds of flagging require a bend in the flaggingStartStop field.
                if (leg.bends != null && leg.bends.Length > 0) {
                    // Already have a bend we can use.
                    leg.flagStartStop = (flagging == FlaggingKind.Begin) ? leg.bends[leg.bends.Length - 1] : leg.bends[0];
                }
                else {
                    // Create a bend half-way along the leg.
                    leg.flagStartStop = new PointF((control1.location.X + control2.location.X) / 2, (control1.location.Y + control2.location.Y) / 2);
                    leg.bends = new PointF[] { leg.flagStartStop };
                }
            }

            // Update the leg object.
            if (legId.IsNone)
                eventDB.AddLeg(leg);
            else {
                if (leg.IsVacuous())
                    eventDB.RemoveLeg(legId);
                else
                    eventDB.ReplaceLeg(legId, leg);
            }

            // Update the finish control symbol if reasonable.
            if (control2.kind == ControlPointKind.Finish) {
                // Update the finish control symbol.
                if ((flagging == FlaggingKind.None || flagging == FlaggingKind.Begin) && control2.symbolIds[0] == "14.1") {
                    // Remove the "flagged from last control symbol" and change it to "no flagging".
                    ChangeDescriptionSymbol(eventDB, controlId2, 0, "14.3");
                }
                else if (flagging == FlaggingKind.End) {
                    // If partial flagging on the end part of the leg, change the symbol to finish funnel.
                    ChangeDescriptionSymbol(eventDB, controlId2, 0, "14.2");
                }
            }
        }
예제 #10
0
        // Change the gaps associated with a leg.
        public static void ChangeLegGaps(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, LegGap[] newGaps)
        {
            // Get the leg object for this leg. Create one if needed.
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2);
            Leg leg;
            if (legId.IsNone)
                leg = new Leg(controlId1, controlId2);
            else
                leg = (Leg) eventDB.GetLeg(legId).Clone();

            // Change the gaps.
            leg.gaps = (newGaps == null) ? null : (LegGap[]) newGaps.Clone();

            // Write the change leg object to the event DB. If the leg is vacuous, could involve removing the leg.
            if (leg.IsVacuous()) {
                if (legId.IsNotNone)
                    eventDB.RemoveLeg(legId);
            }
            else {
                if (legId.IsNone)
                    eventDB.AddLeg(leg);
                else
                    eventDB.ReplaceLeg(legId, leg);
            }
        }
예제 #11
0
        // Change the location of a control. Used when dragging a control to a new location, for example.
        public static void ChangeControlLocation(EventDB eventDB, Id<ControlPoint> controlId, PointF newLocation)
        {
            // Check to see if any legs exist that include this control, and if any of those legs have gaps.
            List<LegGapChange> legGapChangeList = new List<LegGapChange>();

            foreach (Id<Leg> legId in eventDB.AllLegIds) {
                Leg leg = eventDB.GetLeg(legId);
                if ((leg.controlId1 == controlId || leg.controlId2 == controlId) && leg.gaps != null)
                    legGapChangeList.Add(new LegGapChange(leg.controlId1, leg.controlId2, QueryEvent.GetLegPath(eventDB, leg.controlId1, leg.controlId2, legId)));
            }

            // Move the control.
            ControlPoint control = eventDB.GetControl(controlId);

            control = (ControlPoint) control.Clone();
            control.location = newLocation;

            eventDB.ReplaceControlPoint(controlId, control);

            // If there are any leg gaps that need to be repositioned, do that.
            if (legGapChangeList.Count > 0) {
                foreach (LegGapChange legGapChange in legGapChangeList) {
                    Id<Leg> legId = QueryEvent.FindLeg(eventDB, legGapChange.controlId1, legGapChange.controlId2);
                    if (legId.IsNotNone) {
                        Leg leg = (Leg) eventDB.GetLeg(legId).Clone();
                        SymPath newPath = QueryEvent.GetLegPath(eventDB, legGapChange.controlId1, legGapChange.controlId2, legId);
                        LegGap[] newGaps = LegGap.MoveGapsToNewPath(leg.gaps, legGapChange.legPath, newPath);
                        ChangeEvent.ChangeLegGaps(eventDB, legGapChange.controlId1, legGapChange.controlId2, newGaps);
                    }
                }
            }
        }
예제 #12
0
        // Add a bend to a leg.
        public static void AddLegBend(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, PointF newBend)
        {
            // Get the leg object for this leg. Create one if needed.
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2);
            Leg leg;
            if (legId.IsNone)
                leg = new Leg(controlId1, controlId2);
            else
                leg = (Leg) eventDB.GetLeg(legId).Clone();
            SymPath oldPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2, legId);

            // Get an array with the start/end points and the bends.
            PointF[] oldBendArray = new PointF[(leg.bends == null) ? 2 : leg.bends.Length + 2];
            if (leg.bends != null)
                Array.Copy(leg.bends, 0, oldBendArray, 1, leg.bends.Length);
            oldBendArray[0] = eventDB.GetControl(controlId1).location;
            oldBendArray[oldBendArray.Length - 1] = eventDB.GetControl(controlId2).location;

            // Insert the new point into the array at the right place.
            PointF[] newBendArray = Util.AddPointToArray(oldBendArray, newBend);

            // Copy the new bend parts into the bends array.
            leg.bends = new PointF[newBendArray.Length - 2];
            Array.Copy(newBendArray, 1, leg.bends, 0, newBendArray.Length - 2);

            // Update the leg.
            if (legId.IsNone)
                eventDB.AddLeg(leg);
            else
                eventDB.ReplaceLeg(legId, leg);

            // If the leg had gaps, update the gaps for the new path.
            if (leg.gaps != null) {
                SymPath newPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2);
                LegGap[] newGaps = LegGap.MoveGapsToNewPath(leg.gaps, oldPath, newPath);
                ChangeLegGaps(eventDB, controlId1, controlId2, newGaps);
            }
        }
예제 #13
0
        // Remove a bend from a leg.
        public static void RemoveLegBend(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, PointF bendToRemove)
        {
            bool newFlagging = false;
            FlaggingKind newFlaggingKind = FlaggingKind.None;

            // Get the leg object for this leg. One must exists
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2);
            Leg leg = (Leg) eventDB.GetLeg(legId).Clone();
            SymPath oldPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2, legId);

            if (leg.flagging == FlaggingKind.Begin || leg.flagging == FlaggingKind.End && leg.flagStartStop == bendToRemove) {
                // We are removing the point at which flagging starts/stop. The start/stop point must move to another, unless there are no
                // other bends left.
                if (leg.bends.Length == 1) {
                    // No other bends left. Make leg all flagging.
                    newFlagging = true;
                    newFlaggingKind = FlaggingKind.All;
                }
                else {
                    // Basic idea is to move to the bend that is at the flagging end, unless there is no such bend.

                    // Where is the bend?
                    int index = Array.IndexOf(leg.bends, bendToRemove);

                    if ((index == 0 || leg.flagging == FlaggingKind.End) && index != leg.bends.Length - 1) {
                        // move to next bend after the one removed.
                        leg.flagStartStop = leg.bends[index + 1];
                    }
                    else {
                        // move to previous bend before the one removed.
                        leg.flagStartStop = leg.bends[index - 1];
                    }
                }
            }

            // Remove the bend from the bend array.
            leg.bends = Util.RemovePointFromArray(leg.bends, bendToRemove);
            if (leg.bends.Length == 0)
                leg.bends = null;

            // Update the leg objects.
            if (leg.IsVacuous())
                eventDB.RemoveLeg(legId);
            else
                eventDB.ReplaceLeg(legId, leg);

            // Change flagging if we need to. This is more complex that just setting the flagging kind in the leg object.
            if (newFlagging)
                ChangeFlagging(eventDB, controlId1, controlId2, newFlaggingKind);

            // If the leg had gaps, update the gaps for the new path.
            if (leg.gaps != null) {
                SymPath newPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2);
                LegGap[] newGaps = LegGap.MoveGapsToNewPath(leg.gaps, oldPath, newPath);
                ChangeLegGaps(eventDB, controlId1, controlId2, newGaps);
            }
        }
예제 #14
0
        // Removes a control from the event. If the control is present in any course as a course-control, those
        // course-controls are also removed.
        public static void RemoveControl(EventDB eventDB, Id<ControlPoint> controlId)
        {
            // Find all of the courses/course-controls that are this control.
            foreach (Id<Course> courseId in QueryEvent.CoursesUsingControl(eventDB, controlId)) {
                Id<CourseControl> courseControlId;
                do {
                    // Remove one course control could remove multiple, so only remove first of the course controls that use that control, then
                    // check again.
                    courseControlId = QueryEvent.GetCourseControlsInCourse(eventDB, new CourseDesignator(courseId), controlId).FirstOrDefault();
                    if (courseControlId.IsNotNone)
                        RemoveCourseControl(eventDB, courseId, courseControlId);
                } while (courseControlId.IsNotNone);
            }

            // Find all of the legs that use this control and remove them.
            List<Id<Leg>> legIdList = new List<Id<Leg>>();

            foreach (Id<Leg> legId in eventDB.AllLegIds) {
                Leg leg = eventDB.GetLeg(legId);
                if (leg.controlId1 == controlId || leg.controlId2 == controlId)
                    legIdList.Add(legId);
            }
            foreach (Id<Leg> legId in legIdList)
                eventDB.RemoveLeg(legId);

            // Remove the control point itself.
            eventDB.RemoveControlPoint(controlId);
        }
예제 #15
0
        // Move the bend in a leg to a new location.
        public static void MoveLegBend(EventDB eventDB, Id<ControlPoint> controlId1, Id<ControlPoint> controlId2, PointF oldBend, PointF newBend)
        {
            // Get the old leg.
            Id<Leg> legId = QueryEvent.FindLeg(eventDB, controlId1, controlId2);
            Debug.Assert(legId.IsNotNone);
            Leg leg = (Leg) eventDB.GetLeg(legId).Clone();
            SymPath oldPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2, legId);

            // Change the bend.
            for (int i = 0; i < leg.bends.Length; ++i) {
                if (leg.bends[i] == oldBend)
                    leg.bends[i] = newBend;
            }
            if (leg.flagStartStop == oldBend)
                leg.flagStartStop = newBend;

            // Update the leg.
            eventDB.ReplaceLeg(legId, leg);

            // If the leg had gaps, update the gaps for the new path.
            if (leg.gaps != null) {
                SymPath newPath = QueryEvent.GetLegPath(eventDB, controlId1, controlId2);
                leg.gaps = LegGap.MoveGapsToNewPath(leg.gaps, oldPath, newPath);
                eventDB.ReplaceLeg(legId, leg);
            }
        }