/// <summary> /// Returns true if the given vertex has been visited already. /// </summary> /// <param name="vertex"></param> /// <returns></returns> public bool HasBeenVisited(PathSegment<long> vertex) { if(vertex.From != null) { // there is a previous vertex, check it. return this.HasBeenVisited(vertex.VertexId, vertex.From.VertexId); } return _visited.Contains(vertex.VertexId); }
private void InitProperties(Uri uri) { var auth = uri.UserInfo.Split(':'); Username = auth[0]; if (auth.Length == 2) { Password = auth[1]; } else if(auth.Length > 2) { throw new ArgumentException(String.Format( "User info ({0}) cannot have more than two parts.", uri.UserInfo)); } Segments = new PathSegment[uri.Segments.Length]; for(var i = 0; i < uri.Segments.Length; i++) { Segments[i] = new PathSegment(uri.Segments[i]); } if (Query.Length > 0) { foreach (var pairStr in uri.Query.Substring(1).Split('&')) { var pair = pairStr.Split('='); if (pair.Length == 1) { // ReSharper disable AssignNullToNotNullAttribute QueryParameters.Add(null, pair[0]); // ReSharper restore AssignNullToNotNullAttribute } else if (pair.Length == 2) { QueryParameters.Add(pair[0], pair[1]); } else { throw new UriFormatException(String.Format( "Query parameter '{0}' must be in key=value format", pairStr)); } } } }
public void TestPathSegmentConcatenation() { PathSegment<long> segment12 = new PathSegment<long>(2, 10, new PathSegment<long>(1)); // 1 -> 2 PathSegment<long> segment23 = new PathSegment<long>(3, 20, new PathSegment<long>(2)); // 2 -> 3 PathSegment<long> segment_123 = segment23.ConcatenateAfter(segment12); Assert.AreEqual(3, segment_123.VertexId); Assert.AreEqual(2, segment_123.From.VertexId); Assert.AreEqual(1, segment_123.From.From.VertexId); Assert.AreEqual(30, segment_123.Weight); PathSegment<long> segment123 = new PathSegment<long>(3, 22, new PathSegment<long>(2, 10, new PathSegment<long>(1))); // 1 -> 2 -> 3 PathSegment<long> segment345 = new PathSegment<long>(5, 23, new PathSegment<long>(4, 20, new PathSegment<long>(3))); // 3 -> 4 -> 5 PathSegment<long> segment_12345 = segment345.ConcatenateAfter(segment123); Assert.AreEqual(5, segment_12345.VertexId); Assert.AreEqual(4, segment_12345.From.VertexId); Assert.AreEqual(3, segment_12345.From.From.VertexId); Assert.AreEqual(2, segment_12345.From.From.From.VertexId); Assert.AreEqual(1, segment_12345.From.From.From.From.VertexId); Assert.AreEqual(45, segment_12345.Weight); }
public void TestPathSegmentEqualityOperator() { PathSegment<long> segment1 = new PathSegment<long>(1); PathSegment<long> segment1_clone = new PathSegment<long>(1); Assert.IsTrue(segment1 == segment1_clone); Assert.IsFalse(segment1 != segment1_clone); PathSegment<long> segment2 = new PathSegment<long>(2, 10, segment1); PathSegment<long> segment2_clone = new PathSegment<long>(2, 10, segment1_clone); Assert.IsTrue(segment2 == segment2_clone); Assert.IsFalse(segment2 != segment2_clone); PathSegment<long> segment2_different_weight = new PathSegment<long>(2, 11, segment1_clone); Assert.IsFalse(segment2 == segment2_different_weight); Assert.IsTrue(segment2 != segment2_different_weight); PathSegment<long> segment2_different = new PathSegment<long>(2); Assert.IsFalse(segment2 == segment2_different); Assert.IsTrue(segment2 != segment2_different); }
/// <summary> /// Called right after the contraction. /// </summary> /// <param name="vertex"></param> /// <param name="edges"></param> void pre_processor_OnAfterContractionEvent(uint vertex, KeyValuePair <uint, CHEdgeData>[] edges) { // create a new CHRouter var router = new CHRouter(); // calculate all the routes between the neighbours of the contracted vertex. foreach (KeyValuePair <uint, CHEdgeData> from in edges) { // initialize the from-list. var fromList = new PathSegmentVisitList(); fromList.UpdateVertex(new PathSegment <long>(from.Key)); // initalize the from dictionary. Dictionary <uint, PathSegment <long> > fromDic = _pathsBeforeContraction[from.Key]; foreach (KeyValuePair <uint, CHEdgeData> to in edges) { // initialize the to-list. var toList = new PathSegmentVisitList(); toList.UpdateVertex(new PathSegment <long>(to.Key)); // calculate the route. PathSegment <long> route = router.Calculate(_data, _interpreter, OsmSharp.Routing.Vehicle.Car, fromList, toList, double.MaxValue, null); if ((fromDic[to.Key] == null && route != null) || (fromDic[to.Key] != null && route == null) || ((fromDic[to.Key] != null && route != null) && fromDic[to.Key] != route)) { // the route match! Assert.Fail("Routes are different before/after contraction!"); } } } if (_referenceRouter != null) { // do crazy verification! Router chRouter = Router.CreateCHFrom(_data, router, new OsmRoutingInterpreter()); // loop over all nodes and resolve their locations. var resolvedReference = new RouterPoint[_data.VertexCount - 1]; var resolved = new RouterPoint[_data.VertexCount - 1]; for (uint idx = 1; idx < _data.VertexCount; idx++) { // resolve each vertex. float latitude, longitude; if (_data.GetVertex(idx, out latitude, out longitude)) { resolvedReference[idx - 1] = _referenceRouter.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude)); resolved[idx - 1] = chRouter.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude)); } Assert.IsNotNull(resolvedReference[idx - 1]); Assert.IsNotNull(resolved[idx - 1]); Assert.AreEqual(resolvedReference[idx - 1].Location.Latitude, resolved[idx - 1].Location.Latitude, 0.0001); Assert.AreEqual(resolvedReference[idx - 1].Location.Longitude, resolved[idx - 1].Location.Longitude, 0.0001); } // limit tests to a fixed number. int maxTestCount = 100; int testEveryOther = (resolved.Length * resolved.Length) / maxTestCount; testEveryOther = System.Math.Max(testEveryOther, 1); // check all the routes having the same weight(s). for (int fromIdx = 0; fromIdx < resolved.Length; fromIdx++) { for (int toIdx = 0; toIdx < resolved.Length; toIdx++) { int testNumber = fromIdx * resolved.Length + toIdx; if (testNumber % testEveryOther == 0) { Route referenceRoute = _referenceRouter.Calculate(Vehicle.Car, resolvedReference[fromIdx], resolvedReference[toIdx]); Route route = chRouter.Calculate(Vehicle.Car, resolved[fromIdx], resolved[toIdx]); if (referenceRoute != null) { Assert.IsNotNull(referenceRoute); Assert.IsNotNull(route); this.CompareRoutes(referenceRoute, route); } } } } } }
/// <summary> /// Sets the vertex as visited coming from the given vertex. /// </summary> /// <param name="vertex"></param> /// <returns></returns> public void SetVisited(PathSegment<long> vertex) { if (vertex.From != null) { // there is a previous vertex, check it. this.SetVisited(vertex.VertexId, vertex.From.VertexId); } else { _visited.Add(vertex.VertexId); } }
public static bool IsStroked(this PathSegment pathSegment) => pathSegment.IsStroked;
protected override ActionModelNode CloneNode(PathSegment pathSegment) { return new BranchNode(pathSegment); }
public void Test_Constructor_NullLocalized() { var p = new PathSegment("a", (string)null); Assert.AreEqual("a", p.ResourceKey); Assert.AreEqual(null, p.LocalizedText); }
/// <summary> /// Compares the two paths. /// </summary> /// <param name="expected"></param> /// <param name="actual"></param> protected void ComparePaths(PathSegment<long> expected, PathSegment<long> actual) { Assert.AreEqual(expected.VertexId, actual.VertexId); Assert.AreEqual(expected.Weight, actual.Weight, 0.001); if(expected.From != null) { Assert.IsNotNull(actual.From); this.ComparePaths(expected.From, actual.From); return; } Assert.IsNull(actual.From); }
/// <summary> /// Finds a child of this node, based on the specified <see cref="PathSegment"/>. /// </summary> protected ActionModelNode FindChild(PathSegment segment) { return _childNodes[segment.LocalizedText]; }
/// <summary> /// Does dykstra calculation(s) with several options. /// </summary> /// <param name="graph"></param> /// <param name="interpreter"></param> /// <param name="vehicle"></param> /// <param name="source"></param> /// <param name="targets"></param> /// <param name="weight"></param> /// <param name="stopAtFirst"></param> /// <param name="returnAtWeight"></param> /// <param name="forward"></param> /// <returns></returns> private PathSegment <long>[] DoCalculation(IDynamicGraphReadOnly <LiveEdge> graph, IRoutingInterpreter interpreter, Vehicle vehicle, PathSegmentVisitList source, PathSegmentVisitList[] targets, double weight, bool stopAtFirst, bool returnAtWeight, bool forward) { // initialize the result data structures. var segmentsAtWeight = new List <PathSegment <long> >(); var segmentsToTarget = new PathSegment <long> [targets.Length]; // the resulting target segments. long foundTargets = 0; // intialize dykstra data structures. IPriorityQueue <PathSegment <long> > heap = new BinairyHeap <PathSegment <long> >(); var chosenVertices = new HashSet <long>(); var labels = new Dictionary <long, IList <RoutingLabel> >(); foreach (long vertex in source.GetVertices()) { labels[vertex] = new List <RoutingLabel>(); PathSegment <long> path = source.GetPathTo(vertex); heap.Push(path, (float)path.Weight); } // set the from node as the current node and put it in the correct data structures. // intialize the source's neighbours. PathSegment <long> current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } // test each target for the source. // test each source for any of the targets. var pathsFromSource = new Dictionary <long, PathSegment <long> >(); foreach (long sourceVertex in source.GetVertices()) { // get the path to the vertex. PathSegment <long> sourcePath = source.GetPathTo(sourceVertex); // get the source path. sourcePath = sourcePath.From; while (sourcePath != null) { // add the path to the paths from source. pathsFromSource[sourcePath.VertexId] = sourcePath; sourcePath = sourcePath.From; } } // loop over all targets for (int idx = 0; idx < targets.Length; idx++) { // check for each target if there are paths to the source. foreach (long targetVertex in targets[idx].GetVertices()) { PathSegment <long> targetPath = targets[idx].GetPathTo(targetVertex); // get the target path. targetPath = targetPath.From; while (targetPath != null) { // add the path to the paths from source. PathSegment <long> pathFromSource; if (pathsFromSource.TryGetValue(targetPath.VertexId, out pathFromSource)) { // a path is found. // get the existing path if any. PathSegment <long> existing = segmentsToTarget[idx]; if (existing == null) { // a path did not exist yet! segmentsToTarget[idx] = targetPath.Reverse().ConcatenateAfter(pathFromSource); foundTargets++; } else if (existing.Weight > targetPath.Weight + pathFromSource.Weight) { // a new path is found with a lower weight. segmentsToTarget[idx] = targetPath.Reverse().ConcatenateAfter(pathFromSource); } } targetPath = targetPath.From; } } } if (foundTargets == targets.Length && targets.Length > 0) { // routing is finished! return(segmentsToTarget.ToArray()); } if (stopAtFirst) { // only one entry is needed. if (foundTargets > 0) { // targets found, return the shortest! PathSegment <long> shortest = null; foreach (PathSegment <long> foundTarget in segmentsToTarget) { if (shortest == null) { shortest = foundTarget; } else if (foundTarget != null && shortest.Weight > foundTarget.Weight) { shortest = foundTarget; } } segmentsToTarget = new PathSegment <long> [1]; segmentsToTarget[0] = shortest; return(segmentsToTarget); } else { // not targets found yet! segmentsToTarget = new PathSegment <long> [1]; } } // test for identical start/end point. for (int idx = 0; idx < targets.Length; idx++) { PathSegmentVisitList target = targets[idx]; if (returnAtWeight) { // add all the reached vertices larger than weight to the results. if (current.Weight > weight) { PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); segmentsAtWeight.Add(toPath); } } else if (target.Contains(current.VertexId)) { // the current is a target! PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath = toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); if (stopAtFirst) { // stop at the first occurance. segmentsToTarget[0] = toPath; return(segmentsToTarget); } else { // normal one-to-many; add to the result. // check if routing is finished. if (segmentsToTarget[idx] == null) { // make sure only the first route is set. foundTargets++; segmentsToTarget[idx] = toPath; if (foundTargets == targets.Length) { // routing is finished! return(segmentsToTarget.ToArray()); } } else if (segmentsToTarget[idx].Weight > toPath.Weight) { // check if the second, third or later is shorter. segmentsToTarget[idx] = toPath; } } } } // start OsmSharp.Routing. KeyValuePair <uint, LiveEdge>[] arcs = graph.GetArcs( Convert.ToUInt32(current.VertexId)); chosenVertices.Add(current.VertexId); // loop until target is found and the route is the shortest! while (true) { // get the current labels list (if needed). IList <RoutingLabel> currentLabels = null; if (interpreter.Constraints != null) { // there are constraints, get the labels. currentLabels = labels[current.VertexId]; labels.Remove(current.VertexId); } float latitude, longitude; graph.GetVertex(Convert.ToUInt32(current.VertexId), out latitude, out longitude); var currentCoordinates = new GeoCoordinate(latitude, longitude); // update the visited nodes. foreach (KeyValuePair <uint, LiveEdge> neighbour in arcs) { // check the tags against the interpreter. TagsCollection tags = this.TagsIndex.Get(neighbour.Value.Tags); if (vehicle.CanTraverse(tags)) { // it's ok; the edge can be traversed by the given vehicle. bool?oneWay = vehicle.IsOneWay(tags); bool canBeTraversedOneWay = (!oneWay.HasValue || oneWay.Value == neighbour.Value.Forward); if ((current.From == null || interpreter.CanBeTraversed(current.From.VertexId, current.VertexId, neighbour.Key)) && // test for turning restrictions. canBeTraversedOneWay && !chosenVertices.Contains(neighbour.Key)) { // the neigbour is forward and is not settled yet! // check the labels (if needed). bool constraintsOk = true; if (interpreter.Constraints != null) { // check if the label is ok. RoutingLabel neighbourLabel = interpreter.Constraints.GetLabelFor( this.TagsIndex.Get(neighbour.Value.Tags)); // only test labels if there is a change. if (currentLabels.Count == 0 || !neighbourLabel.Equals(currentLabels[currentLabels.Count - 1])) { // labels are different, test them! constraintsOk = interpreter.Constraints.ForwardSequenceAllowed(currentLabels, neighbourLabel); if (constraintsOk) { // update the labels. var neighbourLabels = new List <RoutingLabel>(currentLabels); neighbourLabels.Add(neighbourLabel); labels[neighbour.Key] = neighbourLabels; } } else { // set the same label(s). labels[neighbour.Key] = currentLabels; } } if (constraintsOk) { // all constraints are validated or there are none. graph.GetVertex(Convert.ToUInt32(neighbour.Key), out latitude, out longitude); var neighbourCoordinates = new GeoCoordinate(latitude, longitude); // calculate the weight. double weightToNeighbour = vehicle.Weight(tags, currentCoordinates, neighbourCoordinates); // calculate neighbours weight. double totalWeight = current.Weight + weightToNeighbour; // update the visit list; var neighbourRoute = new PathSegment <long>(neighbour.Key, totalWeight, current); heap.Push(neighbourRoute, (float)neighbourRoute.Weight); } } } } // while the visit list is not empty. current = null; if (heap.Count > 0) { // choose the next vertex. current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } if (current != null) { chosenVertices.Add(current.VertexId); } } while (current != null && current.Weight > weight) { if (returnAtWeight) { // add all the reached vertices larger than weight to the results. segmentsAtWeight.Add(current); } // choose the next vertex. current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } } if (current == null) { // route is not found, there are no vertices left // or the search whent outside of the max bounds. break; } // check target. for (int idx = 0; idx < targets.Length; idx++) { PathSegmentVisitList target = targets[idx]; if (target.Contains(current.VertexId)) { // the current is a target! PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath = toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); if (stopAtFirst) { // stop at the first occurance. segmentsToTarget[0] = toPath; return(segmentsToTarget); } else { // normal one-to-many; add to the result. // check if routing is finished. if (segmentsToTarget[idx] == null) { // make sure only the first route is set. foundTargets++; segmentsToTarget[idx] = toPath; if (foundTargets == targets.Length) { // routing is finished! return(segmentsToTarget.ToArray()); } } else if (segmentsToTarget[idx].Weight > toPath.Weight) { // check if the second, third or later is shorter. segmentsToTarget[idx] = toPath; } } } } // get the neigbours of the current node. arcs = graph.GetArcs(Convert.ToUInt32(current.VertexId)); } // return the result. if (!returnAtWeight) { return(segmentsToTarget.ToArray()); } return(segmentsAtWeight.ToArray()); }
public override bool Equals(PathSegment other) => other is PropertySegment propertySegment && string.Equals(PropertyName, propertySegment.PropertyName, StringComparison.OrdinalIgnoreCase);
protected ExtendedBezierBase(PathSegment segment, Point startPoint) : base(segment, startPoint) { NormalizeBezier(); }
/// <summary> /// Draw ticks. /// Ticks can be draw in 8 diffrent ways depends on Placment property and IsDirectionReversed property. /// /// This function also draw selection-tick(s) if IsSelectionRangeEnabled is 'true' and /// SelectionStart and SelectionEnd are valid. /// /// The primary ticks (for Mininum and Maximum value) height will be 100% of TickBar's render size (use Width or Height /// depends on Placement property). /// /// The secondary ticks (all other ticks, including selection-tics) height will be 75% of TickBar's render size. /// /// Brush that use to fill ticks is specified by Shape.Fill property. /// /// Pen that use to draw ticks is specified by Shape.Pen property. /// </summary> protected override void OnRender(DrawingContext dc) { Size size = new Size(ActualWidth, ActualHeight); double range = Maximum - Minimum; double tickLen = 0.0d; // Height for Primary Tick (for Mininum and Maximum value) double tickLen2; // Height for Secondary Tick double logicalToPhysical = 1.0; double progression = 1.0d; Point startPoint = new Point(0d, 0d); Point endPoint = new Point(0d, 0d); // Take Thumb size in to account double halfReservedSpace = ReservedSpace * 0.5; switch (Placement) { case TickBarPlacement.Top: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width)) { return; } size.Width -= ReservedSpace; tickLen = -size.Height; startPoint = new Point(halfReservedSpace, size.Height); endPoint = new Point(halfReservedSpace + size.Width, size.Height); logicalToPhysical = size.Width / range; progression = 1; break; case TickBarPlacement.Bottom: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width)) { return; } size.Width -= ReservedSpace; tickLen = size.Height; startPoint = new Point(halfReservedSpace, 0d); endPoint = new Point(halfReservedSpace + size.Width, 0d); logicalToPhysical = size.Width / range; progression = 1; break; case TickBarPlacement.Left: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height)) { return; } size.Height -= ReservedSpace; tickLen = -size.Width; startPoint = new Point(size.Width, size.Height + halfReservedSpace); endPoint = new Point(size.Width, halfReservedSpace); logicalToPhysical = size.Height / range * -1; progression = -1; break; case TickBarPlacement.Right: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height)) { return; } size.Height -= ReservedSpace; tickLen = size.Width; startPoint = new Point(0d, size.Height + halfReservedSpace); endPoint = new Point(0d, halfReservedSpace); logicalToPhysical = size.Height / range * -1; progression = -1; break; } ; tickLen2 = tickLen * 0.75; // Invert direciton of the ticks if (IsDirectionReversed) { progression = -progression; logicalToPhysical *= -1; // swap startPoint & endPoint Point pt = startPoint; startPoint = endPoint; endPoint = pt; } Pen pen = new Pen(Fill, 1.0d); bool snapsToDevicePixels = SnapsToDevicePixels; DoubleCollection xLines = snapsToDevicePixels ? new DoubleCollection() : null; DoubleCollection yLines = snapsToDevicePixels ? new DoubleCollection() : null; // Is it Vertical? if ((Placement == TickBarPlacement.Left) || (Placement == TickBarPlacement.Right)) { // Reduce tick interval if it is more than would be visible on the screen double interval = TickFrequency; if (interval > 0.0) { double minInterval = (Maximum - Minimum) / size.Height; if (interval < minInterval) { interval = minInterval; } } // Draw Min & Max tick dc.DrawLine(pen, startPoint, new Point(startPoint.X + tickLen, startPoint.Y)); dc.DrawLine(pen, new Point(startPoint.X, endPoint.Y), new Point(startPoint.X + tickLen, endPoint.Y)); if (snapsToDevicePixels) { xLines.Add(startPoint.X); yLines.Add(startPoint.Y - 0.5); xLines.Add(startPoint.X + tickLen); yLines.Add(endPoint.Y - 0.5); xLines.Add(startPoint.X + tickLen2); } // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { ticks = Ticks; } // Draw ticks using specified Ticks collection if ((ticks != null) && (ticks.Count > 0)) { for (int i = 0; i < ticks.Count; i++) { if (DoubleUtil.LessThanOrClose(ticks[i], Minimum) || DoubleUtil.GreaterThanOrClose(ticks[i], Maximum)) { continue; } double adjustedTick = ticks[i] - Minimum; double y = adjustedTick * logicalToPhysical + startPoint.Y; dc.DrawLine(pen, new Point(startPoint.X, y), new Point(startPoint.X + tickLen2, y)); if (snapsToDevicePixels) { yLines.Add(y - 0.5); } } } // Draw ticks using specified TickFrequency else if (interval > 0.0) { for (double i = interval; i < range; i += interval) { double y = i * logicalToPhysical + startPoint.Y; dc.DrawLine(pen, new Point(startPoint.X, y), new Point(startPoint.X + tickLen2, y)); if (snapsToDevicePixels) { yLines.Add(y - 0.5); } } } // Draw Selection Ticks if (IsSelectionRangeEnabled) { double y0 = (SelectionStart - Minimum) * logicalToPhysical + startPoint.Y; Point pt0 = new Point(startPoint.X, y0); Point pt1 = new Point(startPoint.X + tickLen2, y0); Point pt2 = new Point(startPoint.X + tickLen2, y0 + Math.Abs(tickLen2) * progression); PathSegment[] segments = new PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); y0 = (SelectionEnd - Minimum) * logicalToPhysical + startPoint.Y; pt0 = new Point(startPoint.X, y0); pt1 = new Point(startPoint.X + tickLen2, y0); pt2 = new Point(startPoint.X + tickLen2, y0 - Math.Abs(tickLen2) * progression); segments = new PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); } } else // Placement == Top || Placement == Bottom { // Reduce tick interval if it is more than would be visible on the screen double interval = TickFrequency; if (interval > 0.0) { double minInterval = (Maximum - Minimum) / size.Width; if (interval < minInterval) { interval = minInterval; } } // Draw Min & Max tick dc.DrawLine(pen, startPoint, new Point(startPoint.X, startPoint.Y + tickLen)); dc.DrawLine(pen, new Point(endPoint.X, startPoint.Y), new Point(endPoint.X, startPoint.Y + tickLen)); if (snapsToDevicePixels) { xLines.Add(startPoint.X - 0.5); yLines.Add(startPoint.Y); xLines.Add(startPoint.X - 0.5); yLines.Add(endPoint.Y + tickLen); yLines.Add(endPoint.Y + tickLen2); } // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { ticks = Ticks; } // Draw ticks using specified Ticks collection if ((ticks != null) && (ticks.Count > 0)) { for (int i = 0; i < ticks.Count; i++) { if (DoubleUtil.LessThanOrClose(ticks[i], Minimum) || DoubleUtil.GreaterThanOrClose(ticks[i], Maximum)) { continue; } double adjustedTick = ticks[i] - Minimum; double x = adjustedTick * logicalToPhysical + startPoint.X; dc.DrawLine(pen, new Point(x, startPoint.Y), new Point(x, startPoint.Y + tickLen2)); if (snapsToDevicePixels) { xLines.Add(x - 0.5); } } } // Draw ticks using specified TickFrequency else if (interval > 0.0) { for (double i = interval; i < range; i += interval) { double x = i * logicalToPhysical + startPoint.X; dc.DrawLine(pen, new Point(x, startPoint.Y), new Point(x, startPoint.Y + tickLen2)); if (snapsToDevicePixels) { xLines.Add(x - 0.5); } } } // Draw Selection Ticks if (IsSelectionRangeEnabled) { double x0 = (SelectionStart - Minimum) * logicalToPhysical + startPoint.X; Point pt0 = new Point(x0, startPoint.Y); Point pt1 = new Point(x0, startPoint.Y + tickLen2); Point pt2 = new Point(x0 + Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); PathSegment[] segments = new PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); x0 = (SelectionEnd - Minimum) * logicalToPhysical + startPoint.X; pt0 = new Point(x0, startPoint.Y); pt1 = new Point(x0, startPoint.Y + tickLen2); pt2 = new Point(x0 - Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); segments = new PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); } } if (snapsToDevicePixels) { xLines.Add(ActualWidth); yLines.Add(ActualHeight); VisualXSnappingGuidelines = xLines; VisualYSnappingGuidelines = yLines; } return; }
private static PathSegment Copy(PathSegment s) { if (s == null) { return(null); } LineSegment ls = s as LineSegment; if (ls != null) { return(new LineSegment() { Point = ls.Point }); } BezierSegment bs = s as BezierSegment; if (bs != null) { return(new BezierSegment() { Point1 = bs.Point1, Point2 = bs.Point2, Point3 = bs.Point3 }); } QuadraticBezierSegment qbs = s as QuadraticBezierSegment; if (qbs != null) { return(new QuadraticBezierSegment() { Point1 = qbs.Point1, Point2 = qbs.Point2 }); } ArcSegment arc = s as ArcSegment; if (arc != null) { return(new ArcSegment() { Point = arc.Point, Size = arc.Size, SweepDirection = arc.SweepDirection, IsLargeArc = arc.IsLargeArc, RotationAngle = arc.RotationAngle }); } PolyLineSegment pls = s as PolyLineSegment; if (pls != null) { return(new PolyLineSegment() { Points = Copy(pls.Points) }); } PolyBezierSegment pbs = s as PolyBezierSegment; if (pbs != null) { return(new PolyBezierSegment() { Points = Copy(pbs.Points) }); } PolyQuadraticBezierSegment pqbs = s as PolyQuadraticBezierSegment; if (pqbs != null) { return(new PolyQuadraticBezierSegment() { Points = Copy(pqbs.Points) }); } Diagram.Error("Copying an unknown kind of PathSegment: " + s.ToString()); return(null); }
/// <summary> /// Finds a valid vertex for the given vertex but does not search in the direction of the target neighbour. /// </summary> /// <param name="vertex">The invalid vertex.</param> /// <param name="edge">The edge that leads to the target vertex.</param> /// <param name="targetVertex">The target vertex.</param> /// <param name="excludeSet">The set of vertices that should be excluded in the search.</param> /// <param name="searchForward">When true, the search is forward, otherwise backward.</param> public virtual PathSegment FindValidVertexFor(long vertex, LiveEdge edge, long targetVertex, HashSet <long> excludeSet, bool searchForward) { // GIST: execute a dykstra search to find a vertex that is valid. // this will return a vertex that is on the shortest path: // foundVertex -> vertex -> targetNeighbour. // initialize settled set. var settled = new HashSet <long>(); settled.Add(targetVertex); // initialize heap. var heap = new BinaryHeap <PathSegment>(10); heap.Push(new PathSegment(vertex), 0); // find the path to the closest valid vertex. PathSegment pathTo = null; while (heap.Count > 0) { // get next. var current = heap.Pop(); if (settled.Contains(current.Vertex)) { // don't consider vertices twice. continue; } settled.Add(current.Vertex); // limit search. if (settled.Count > BasicRouter.MaxSettles) { // not valid vertex found. return(null); } // check if valid. if (current.Vertex != vertex && this.IsVertexValid(current.Vertex)) { // ok! vertex is valid. pathTo = current; } else { // continue search. // add unsettled neighbours. var arcs = this.Graph.GetEdges(current.Vertex); foreach (var arc in arcs) { if (!excludeSet.Contains(arc.Key) && !settled.Contains(arc.Key) && !(current.Vertex == vertex && arc.Key == targetVertex && edge.Distance == arc.Value.Distance)) { // ok, new neighbour, and ok, not the edge and neighbour to ignore. var tags = this.Graph.TagsIndex.Get(arc.Value.Tags); if (this.Vehicle.CanTraverse(tags)) { // ok, we can traverse this edge. var oneway = this.Vehicle.IsOneWay(tags); if (oneway == null || !(oneway.Value == arc.Value.Forward ^ searchForward)) { // ok, no oneway or oneway reversed. var weight = this.Vehicle.Weight(this.Graph.TagsIndex.Get(arc.Value.Tags), arc.Value.Distance); var path = new PathSegment(arc.Key, current.Weight + weight, arc.Value, current); heap.Push(path, (float)path.Weight); } } } } } } // ok, is there a path found. if (pathTo == null) { // oeps, probably something wrong with network-topology. // just take the default option. //throw new Exception( // string.Format("Could not find a valid vertex for invalid vertex [{0}].", vertex)); return(null); } // add the path to the given location. return(pathTo); }
/// <summary> /// Parses a PathGeometry from a data string element. /// </summary> PathGeometry ParsePathGeometry(string data) { #if DEBUG_ // XPS = M 20,100 C 45,50 70,150 95,100 S 145,150 170,100 220,150 245,100 C 220,50 195,150 170,100 S 120,150 95,100 45,150 20,100 // XXX = M20,100C45,50 70,150 95,100 120,50 145,150 170,100 195,50 220,150 245,100 220,50 195,150 170,100 145,50 120,150 95,100 70,50 45,150 20,100 if (data.StartsWith("M 20,100 C 45,50 70,150 95,100 S 145,")) { Debugger.Break(); } #endif PathGeometry geo = TryParseStaticResource <PathGeometry>(data); if (geo != null) { return(geo); } data = FixHack(data); // From the algorithm on page 365 in XPS 1.0 specs // See Petzold page 813 geo = new PathGeometry(); Point point = new Point(); PathFigure figure = null; TokenizerHelper helper = new TokenizerHelper(data); helper.NextTokenRequired(); do { string token = helper.GetCurrentToken(); switch (token[0]) { // FillRule case 'F': geo.FillRule = helper.NextTokenRequired() == "1" ? FillRule.NonZero : FillRule.EvenOdd; break; // Move case 'M': { figure = new PathFigure(); geo.Figures.Add(figure); point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); figure.StartPoint = point; } break; // Move case 'm': { figure = new PathFigure(); geo.Figures.Add(figure); point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())); figure.StartPoint = point; } break; // Line case 'L': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Line case 'l': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Horizontal Line case 'H': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point.X = ParseDouble(helper.NextTokenRequired()); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Horizontal Line case 'h': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point.X += ParseDouble(helper.NextTokenRequired()); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Vertical Line case 'V': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point.Y = ParseDouble(helper.NextTokenRequired()); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Vertical Line case 'v': { PolyLineSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null) { } else { seg = new PolyLineSegment(); figure.Segments.Add(seg); } do { point.Y += ParseDouble(helper.NextTokenRequired()); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Elliptical Arc case 'A': do { // I cannot believe it: "A70.1,50.1 1,34 0 0 170.1,30.1" // The rotation angle "1,34" uses a ',' instead of a '.' in my German Windows Vista! //A70.1,50.1 1,34 0 0 170.1,30.1 ArcSegment seg = new ArcSegment(); figure.Segments.Add(seg); seg.Size = new Size(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.RotationAngle = ParseDouble(helper.NextTokenRequired()); seg.IsLargeArc = helper.NextTokenRequired() == "1"; seg.SweepDirection = helper.NextTokenRequired() == "1" ? SweepDirection.Clockwise : SweepDirection.Counterclockwise; point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Point = point; } while (!Char.IsLetter(helper.PeekNextCharacter())); break; // Elliptical Arc case 'a': do { ArcSegment seg = new ArcSegment(); figure.Segments.Add(seg); seg.Size = new Size(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.RotationAngle = ParseDouble(helper.NextTokenRequired()); seg.IsLargeArc = helper.NextTokenRequired() == "1"; seg.SweepDirection = helper.NextTokenRequired() == "1" ? SweepDirection.Clockwise : SweepDirection.Counterclockwise; point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())); seg.Point = point; } while (!Char.IsLetter(helper.PeekNextCharacter())); break; // Cubic Bézier Curve case 'C': { PolyBezierSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null) { } else { seg = new PolyBezierSegment(); figure.Segments.Add(seg); } do { seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()))); seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()))); point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Cubic Bézier Curve case 'c': { PolyBezierSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null) { } else { seg = new PolyBezierSegment(); figure.Segments.Add(seg); } do { seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()))); seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()))); point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Smooth Cubic Bézier Curve case 'S': { PolyBezierSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null) { } else { seg = new PolyBezierSegment(); figure.Segments.Add(seg); } do { Point pt = new Point(); int count = seg.Points.Count; segCount = figure.Segments.Count; if (count > 0) { Point lastCtrlPoint = seg.Points[count - 2]; pt.X = 2 * point.X - lastCtrlPoint.X; pt.Y = 2 * point.Y - lastCtrlPoint.Y; } else if (segCount > 1 && figure.Segments[count - 2] is PolyBezierSegment) { PolyBezierSegment lastSeg = (PolyBezierSegment)figure.Segments[count - 2]; count = lastSeg.Points.Count; Point lastCtrlPoint = lastSeg.Points[count - 2]; pt.X = 2 * point.X - lastCtrlPoint.X; pt.Y = 2 * point.Y - lastCtrlPoint.Y; } else { pt = point; } seg.Points.Add(pt); seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()))); point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Smooth Cubic Bézier Curve case 's': { PolyBezierSegment seg; int segCount = figure.Segments.Count; if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null) { } else { seg = new PolyBezierSegment(); figure.Segments.Add(seg); } do { Point pt = new Point(); int count = seg.Points.Count; segCount = figure.Segments.Count; if (count > 0) { Point lastCtrlPoint = seg.Points[count - 2]; pt.X = 2 * point.X - lastCtrlPoint.X; pt.Y = 2 * point.Y - lastCtrlPoint.Y; } else if (segCount > 1 && figure.Segments[count - 2] is PolyBezierSegment) { PolyBezierSegment lastSeg = (PolyBezierSegment)figure.Segments[count - 2]; count = lastSeg.Points.Count; Point lastCtrlPoint = lastSeg.Points[count - 2]; pt.X = 2 * point.X - lastCtrlPoint.X; pt.Y = 2 * point.Y - lastCtrlPoint.Y; } else { pt = point; } seg.Points.Add(pt); seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()))); point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Quadratic Bézier Curve case 'Q': { PolyQuadraticBezierSegment seg = new PolyQuadraticBezierSegment(); figure.Segments.Add(seg); do { seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()))); point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Quadratic Bézier Curve case 'q': { PolyQuadraticBezierSegment seg = new PolyQuadraticBezierSegment(); figure.Segments.Add(seg); do { seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()))); point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())); seg.Points.Add(point); } while (!Char.IsLetter(helper.PeekNextCharacter())); } break; // Close case 'Z': case 'z': { figure.IsClosed = true; if (figure.Segments.Count > 0) { PathSegment seg = figure.Segments[0]; } point = figure.StartPoint; figure = null; } break; default: Debug.Assert(false); break; } } while (helper.NextToken()); return(geo); }
protected AbstractActionModelTreeLeaf(PathSegment pathSegment) : base(pathSegment) {}
/// <summary> /// Sucht ein Item anahnd der ID /// </summary> /// <param name="uri">Der Pfad zu der Ressource</param> /// <returns>Das Item oder null</returns> public SearchResult Find(IUri uri) { if (uri == null || uri.Path.Count == 0) { return(null); } var current = uri.Take(1); var next = uri.Skip(1); var match = false; var uriSegment = current.Path.FirstOrDefault()?.ToString(); var pathSegment = PathSegment?.ToString(); var variables = null as IDictionary <string, string>; if (string.IsNullOrWhiteSpace(pathSegment) && string.IsNullOrWhiteSpace(uriSegment)) { match = true; } else if (PathSegment is PathSegmentConstant && pathSegment.Equals(uriSegment, StringComparison.OrdinalIgnoreCase)) { match = true; } else if (PathSegment is PathSegmentVariable variable && Regex.IsMatch(uriSegment, pathSegment, RegexOptions.IgnoreCase)) { match = true; variables = variable.GetVariables(uriSegment); } if (match && IncludeSubPaths) { return(new SearchResult ( Title, Type, ModuleContext, ResourceContext, Path, variables )); } else if (match && next == null) { return(new SearchResult ( Title, Type, ModuleContext, ResourceContext, Path, variables )); } else if (match && Children.Count > 0) { foreach (var child in Children) { var result = child.Find(next); if (result != null) { result.AddVariables(variables); return(result); } } } return(null); }
public void TestPathSegmentReverse() { // define segment 4 -(10)> 3 -(10)> 2 -(10)> 1 var segment = new PathSegment<long>(1, 30, new PathSegment<long>(2, 20, new PathSegment<long>(3, 10, new PathSegment<long>(4)))); // reverse segment to 1 -(10)> 2 -(20)> 3 -(30)> 4 var reverse = segment.Reverse(); Assert.AreEqual(segment.Weight, reverse.Weight); Assert.AreEqual(4, reverse.VertexId); Assert.AreEqual(3, reverse.From.VertexId); Assert.AreEqual(20, reverse.From.Weight); Assert.AreEqual(2, reverse.From.From.VertexId); Assert.AreEqual(10, reverse.From.From.Weight); Assert.AreEqual(1, reverse.From.From.From.VertexId); Assert.AreEqual(0, reverse.From.From.From.Weight); }
protected AbstractActionModelTreeNode(PathSegment pathSegment) { Platform.CheckForNullReference(pathSegment, "pathSegment"); _pathSegment = pathSegment; }
/// <inheritdoc /> public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values is null) { return(new PathFigureCollection(0)); } if (values.Length != 9) { throw new ArgumentException( $"{nameof(EdgeRouteToPathConverter)} must have 9 parameters: pos (1,2), size (3,4) of source; pos (5,6), size (7,8) of target; routeInformation (9).", nameof(values)); } ExtractInputs( values, out Point sourcePos, out Point targetPos, out Size sourceSize, out Size targetSize, out System.Windows.Point[] routeInformation); bool hasRouteInfo = routeInformation != null && routeInformation.Length > 0; // Create the path System.Windows.Point p1 = LayoutUtils.GetClippingPoint( sourceSize, sourcePos, hasRouteInfo ? routeInformation[0].ToGraphShapePoint() : targetPos).ToPoint(); System.Windows.Point p2 = LayoutUtils.GetClippingPoint( targetSize, targetPos, hasRouteInfo ? routeInformation[routeInformation.Length - 1].ToGraphShapePoint() : sourcePos).ToPoint(); var segments = new PathSegment[1 + (hasRouteInfo ? routeInformation.Length : 0)]; if (hasRouteInfo) { // Append route points for (int i = 0; i < routeInformation.Length; ++i) { segments[i] = new LineSegment(routeInformation[i], true); } } System.Windows.Point pLast = hasRouteInfo ? routeInformation[routeInformation.Length - 1] : p1; System.Windows.Vector v = pLast - p2; v = v / v.Length * 5; var n = new System.Windows.Vector(-v.Y, v.X) * 0.3; segments[segments.Length - 1] = new LineSegment(p2 + v, true); var pathCollection = new PathFigureCollection(2) { new PathFigure(p1, segments, false), new PathFigure( p2, new PathSegment[] { new LineSegment(p2 + v - n, true), new LineSegment(p2 + v + n, true) }, true) }; return(pathCollection); }
public List <Vector2> PathTo(Vector2 from, Vector2 to) { PathSegment startSegment = ClosestSegment(from); PathSegment endSegment = ClosestSegment(to); if (startSegment == endSegment || startSegment == null || endSegment == null) { return(new List <Vector2>() { to }); } //Simple brute force search Dictionary <PathNode, NodeDetail> nodeDetails = new Dictionary <PathNode, NodeDetail>(); List <NodeDetail> nodesToExplore = new List <NodeDetail>(); nodesToExplore.Add(new NodeDetail() { node = startSegment.To, g = (startSegment.To.transform.position2() - from).magnitude }); if (!startSegment.OneWay) { nodesToExplore.Add(new NodeDetail() { node = startSegment.From, g = (startSegment.From.transform.position2() - from).magnitude }); } bool found = false; NodeDetail endNodeDetail = null; while (!found && nodesToExplore.Any()) { nodesToExplore = nodesToExplore.OrderBy(it => it.g + (endSegment.From.transform.position - it.node.transform.position).magnitude ).ToList(); NodeDetail current = nodesToExplore[0]; nodesToExplore.RemoveAt(0); foreach (PathNode next in nodeNeighbors[current.node]) { float delta = (next.transform.position - current.node.transform.position).magnitude; float newG = current.g + delta; if (nodeDetails.ContainsKey(next)) { NodeDetail nextDetail = nodeDetails[next]; if (newG < nextDetail.g) { nextDetail.g = newG; nextDetail.parent = current; } } else { NodeDetail nextDetail = new NodeDetail() { node = next, parent = current, g = newG }; if (next == endSegment.From) { found = true; endNodeDetail = nextDetail; break; } if (!endSegment.OneWay && next == endSegment.To) { found = true; endNodeDetail = nextDetail; break; } nodeDetails[next] = nextDetail; nodesToExplore.Add(nextDetail); } } } if (endNodeDetail == null) { return(null); } List <Vector2> path = new List <Vector2>() { endNodeDetail.node.transform.position, to }; NodeDetail previous = endNodeDetail.parent; while (previous != null) { path.Insert(0, previous.node.transform.position); previous = previous.parent; } return(path); }
/// <summary> /// Used by the <see cref="ActionModelNode.CloneTree"/> method. /// </summary> /// <remarks> /// Derived classes must override this method to return a clone node. This clone should /// not copy the sub-tree. /// </remarks> /// <param name="pathSegment">The path segment which this node represents.</param> /// <returns>A new node of this type.</returns> protected override ActionModelNode CloneNode(PathSegment pathSegment) { return new ActionNode(pathSegment, _action); }
/// <summary> /// Try to bind namespace-qualified type cast segment. /// </summary> internal static bool TryBindTypeCastSegment(string identifier, string parenthesisExpressions, IEdmModel model, IList <PathSegment> path, PathParserSettings settings) { if (identifier == null || identifier.IndexOf('.') < 0) { // type cast should be namespace-qualified name return(false); } PathSegment preSegment = path.LastOrDefault(); if (preSegment == null) { // type cast should not be the first segment. return(false); } IEdmSchemaType schemaType = model.ResolveType(identifier, settings.EnableCaseInsensitive); if (schemaType == null) { return(false); } IEdmType targetEdmType = schemaType as IEdmType; if (targetEdmType == null) { return(false); } IEdmType previousEdmType = preSegment.EdmType; bool isNullable = false; if (previousEdmType.TypeKind == EdmTypeKind.Collection) { previousEdmType = ((IEdmCollectionType)previousEdmType).ElementType.Definition; isNullable = ((IEdmCollectionType)previousEdmType).ElementType.IsNullable; } if (!targetEdmType.IsOrInheritsFrom(previousEdmType) && !previousEdmType.IsOrInheritsFrom(targetEdmType)) { throw new Exception($"Type cast {targetEdmType.FullTypeName()} has no relationship with previous {previousEdmType.FullTypeName()}."); } // We want the type of the type segment to be a collection if the previous segment was a collection IEdmType actualTypeOfTheTypeSegment = targetEdmType; if (preSegment.EdmType.TypeKind == EdmTypeKind.Collection) { var actualEntityTypeOfTheTypeSegment = targetEdmType as IEdmEntityType; if (actualEntityTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmEntityTypeReference(actualEntityTypeOfTheTypeSegment, isNullable)); } else { // Complex collection supports type cast too. var actualComplexTypeOfTheTypeSegment = actualTypeOfTheTypeSegment as IEdmComplexType; if (actualComplexTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmComplexTypeReference(actualComplexTypeOfTheTypeSegment, isNullable)); } else { throw new Exception($"Invalid type cast of {identifier}, it should be entity or complex."); } } } TypeSegment typeCast = new TypeSegment(actualTypeOfTheTypeSegment, preSegment.EdmType, preSegment.NavigationSource, identifier); path.Add(typeCast); TryBindKeySegment(parenthesisExpressions, path); return(true); }
/// <summary> /// Used by the <see cref="ActionModelNode.CloneTree"/> method. /// </summary> /// <param name="pathSegment">The path segment which this node represents.</param> /// <returns>A new node of this type.</returns> protected override ActionModelNode CloneNode(PathSegment pathSegment) { return new ActionModelRoot(); }
public override int GetDestination(string path, PathSegment segment) { return(segment.Length == 0 ? _exitDestination : _defaultDestination); }
public void Test_NullResolver() { var p = new PathSegment("a", (IResourceResolver) null); Assert.AreEqual("a", p.ResourceKey); Assert.AreEqual("a", p.LocalizedText); }
/// <summary> /// Used by the <see cref="ActionModelNode.CloneTree"/> method. /// </summary> /// <param name="pathSegment">The path segment which this node represents.</param> /// <returns>A new node of this type.</returns> protected override ActionModelNode CloneNode(PathSegment pathSegment) { return(new ActionModelRoot()); }
/// <summary> /// Specifies stroke and join options to be applied to new segments added to the geometry sink. /// </summary> /// <param name="vertexFlags">Stroke and join options to be applied to new segments added to the geometry sink.</param> /// <remarks> /// After this method is called, the specified segment flags are applied to each segment subsequently added to the sink. The segment flags are applied to every additional segment until this method is called again and a different set of segment flags is specified. /// </remarks> public void SetSegmentFlags(PathSegment vertexFlags) { SetSegmentFlags_(vertexFlags); }
private void ConvertPart(PathThumb senderThumb, PathPartConvertType convertType) { if (senderThumb.PathPoint.ParentObject is PathFigure) { var pathFigure = senderThumb.PathPoint.ParentObject as PathFigure; var pathSegment = senderThumb.PathPoint.Object as PathSegment; var idx = pathFigure.Segments.IndexOf(pathSegment); var point = senderThumb.PathPoint.Point; if (pathSegment is PolyLineSegment) { var poly = pathSegment as PolyLineSegment; var lst = poly.Points.Take(senderThumb.PathPoint.PolyLineIndex); var lst2 = poly.Points.Skip(senderThumb.PathPoint.PolyLineIndex + 1); var p = poly.Points[senderThumb.PathPoint.PolyLineIndex]; pathFigure.Segments.RemoveAt(idx); var p1 = new PolyLineSegment(); p1.Points.AddRange(lst); pathFigure.Segments.Insert(idx, p1); pathSegment = new LineSegment() { Point = p }; pathFigure.Segments.Insert(idx + 1, pathSegment); var p2 = new PolyLineSegment(); p2.Points.AddRange(lst2); pathFigure.Segments.Insert(idx + 2, p2); idx++; } else if (pathSegment is PolyBezierSegment) { //TODO } else if (pathSegment is PolyQuadraticBezierSegment) { //TODO } pathFigure.Segments.RemoveAt(idx); var midp = senderThumb.PathPoint.ParentPathPoint.Point - ((senderThumb.PathPoint.ParentPathPoint.Point - point) / 2); PathSegment newSegment = null; switch (convertType) { case PathPartConvertType.ToBezierSegment: newSegment = new BezierSegment() { Point1 = midp - new Vector(40, 40), Point2 = midp + new Vector(-40, 40), Point3 = point }; break; case PathPartConvertType.ToQuadricBezierSegment: newSegment = new QuadraticBezierSegment() { Point1 = point - new Vector(40, 40), Point2 = point }; break; case PathPartConvertType.ToArcSegment: newSegment = new ArcSegment() { Point = point, Size = new Size(20, 20) }; break; case PathPartConvertType.insertPoint: pathFigure.Segments.Insert(idx, pathSegment); newSegment = new LineSegment() { Point = midp, }; break; default: newSegment = new LineSegment() { Point = point }; break; } pathFigure.Segments.Insert(idx, newSegment); } this.ExtendedItem.ReapplyAllExtensions(); }
public IEnumerator EvaluateSegmentOverTime() { Evaluating = true; while (mUpcomingSegments.Count > 0) { if (CurrentSegment == null) { CurrentSegment = mUpcomingSegments.Pop(); StartMeters = CurrentSegment.StartMeters; CurrentMeters = StartMeters; EndMeters = CurrentSegment.EndMeters; TotalMeters = CurrentSegment.LengthInMeters; Direction = CurrentSegment.Direction; if (StartMeters > EndMeters) { Direction = PathDirection.Backwards; } else { Direction = PathDirection.Forward; } mEvalPoints.Clear(); } //change layer so we don't hit ourselves in raycast gameObject.layer = Globals.LayerNumHidden; EvalPoint evalPoint = new EvalPoint(); evalPoint.PathPosition = CurrentSegment.ParentPath.PositionFromMeters(CurrentMeters); evalPoint.TerrainPosition = evalPoint.PathPosition; evalPoint.Ground = GroundType.Dirt; //get the terrain data from the game world mTerrainHit.feetPosition = evalPoint.PathPosition; mTerrainHit.groundedHeight = Globals.PlayerControllerHeightDefault; evalPoint.TerrainPosition.y = GameWorld.Get.TerrainHeightAtInGamePosition(ref mTerrainHit); //evalPoint.PathPosition, true, ref evalPoint.HitWater, ref evalPoint.HitTerrainMesh, ref evalPoint.PathNormal); mEvalPoints.Add(evalPoint); //change back so we encounter objects gameObject.layer = Globals.LayerNumTrigger; if (Paths.MoveAlongPath(ref CurrentMeters, MetersPerStep, Direction, StartMeters, EndMeters) == false) //if we're out of range, then we're done with this segment { InterpretEvalPoints(); CurrentSegment = null; } else { transform.position = evalPoint.TerrainPosition; } double start = Frontiers.WorldClock.RealTime; while (Frontiers.WorldClock.RealTime < start + YieldTimePerStep) { yield return(null); } } Evaluating = false; yield break; }
/// <summary> /// Creates a new <see cref="PathGeometry"/> instance that is only initialized /// with a single segment and the specified start position. /// </summary> /// <param name="startPosition">The start position.</param> /// <param name="segment">The single segment of the <see cref="PathGeometry"/>.</param> /// <returns> /// The resulting <see cref="PathGeometry"/> object. /// </returns> public static PathGeometry CreatePathGeometryForSingleSegment(Point startPosition, PathSegment segment) { var figure = new PathFigure { StartPoint = startPosition, Segments = { segment } }; var geometry = new PathGeometry { Figures = new PathFigureCollection { figure } }; return(geometry); }
private static PathSegmentCollection Clone(PathSegmentCollection pathSegColl) { PathSegmentCollection collClone = new PathSegmentCollection(); foreach (PathSegment item in pathSegColl) { PathSegment clone = null; if (item is LineSegment) { LineSegment seg = item as LineSegment; clone = new LineSegment() { Point = seg.Point }; } else if (item is PolyLineSegment) { PolyLineSegment seg = item as PolyLineSegment; clone = new PolyLineSegment() { Points = getPoints(seg.Points) }; } else if (item is BezierSegment) { BezierSegment seg = item as BezierSegment; clone = new BezierSegment() { Point1 = seg.Point1, Point2 = seg.Point2, Point3 = seg.Point3 }; } else if (item is PolyBezierSegment) { PolyBezierSegment seg = item as PolyBezierSegment; clone = new PolyBezierSegment() { Points = getPoints(seg.Points) }; } else if (item is PolyQuadraticBezierSegment) { PolyQuadraticBezierSegment seg = item as PolyQuadraticBezierSegment; clone = new PolyQuadraticBezierSegment() { Points = getPoints(seg.Points) }; } else if (item is QuadraticBezierSegment) { QuadraticBezierSegment seg = item as QuadraticBezierSegment; clone = new QuadraticBezierSegment() { Point1 = seg.Point1, Point2 = seg.Point2 }; } else if (item is Windows.UI.Xaml.Media.ArcSegment) { Windows.UI.Xaml.Media.ArcSegment seg = item as Windows.UI.Xaml.Media.ArcSegment; clone = new Windows.UI.Xaml.Media.ArcSegment() { IsLargeArc = seg.IsLargeArc, Point = seg.Point, RotationAngle = seg.RotationAngle, Size = seg.Size, SweepDirection = seg.SweepDirection }; } collClone.Add(clone); } return(collClone); }
/// <summary> /// Adds a path segment to the backward queue. /// </summary> /// <param name="segment"></param> public void AddBackward(PathSegment<long> segment) { _backward[segment.VertexId] = segment; PathSegment<long> forward; if (_forward.TryGetValue(segment.VertexId, out forward)) { _intersection[segment.VertexId] = forward.Weight + segment.Weight; } }
/// <summary> /// Updates a vertex in this visit list. /// </summary> /// <param name="route"></param> public void UpdateVertex(PathSegment<long> route) { double current_weight; if (_visited.TryGetValue(route.VertexId, out current_weight)) { // the vertex was already in this list. if (current_weight > route.Weight) { // replace the existing. Dictionary<long, PathSegment<long>> current_weight_vertices = _visit_list[current_weight]; current_weight_vertices.Remove(route.VertexId); if (current_weight_vertices.Count == 0) { _visit_list.Remove(current_weight); } } else { // do nothing, the existing weight is better. return; } } // add/update everthing. Dictionary<long, PathSegment<long>> vertices_at_weight; if (!_visit_list.TryGetValue(route.Weight, out vertices_at_weight)) { vertices_at_weight = new Dictionary<long, PathSegment<long>>(); _visit_list.Add(route.Weight, vertices_at_weight); } vertices_at_weight.Add(route.VertexId, route); _visited[route.VertexId] = route.Weight; }
/// <summary> /// Constructor. /// </summary> /// <param name="pathSegment"></param> protected internal SeparatorNode(PathSegment pathSegment) : base(pathSegment) { }
private void DrawSegment (PathSegment segment) { if (segment is LineSegment) { DrawLineSegment (segment as LineSegment); } if (segment is ArcSegment) { DrawArcSegment (segment as ArcSegment); } }
/// <summary> /// Protected constructor. /// </summary> /// <param name="pathSegment">The segment of the action path to which this node corresponds.</param> protected ActionModelNode(PathSegment pathSegment) { _pathSegment = pathSegment; _childNodes = new ActionModelNodeList(); }
/// <summary> /// Specifies stroke and join options to be applied to new segments added to the geometry sink. /// </summary> /// <param name="vertexFlags">Stroke and join options to be applied to new segments added to the geometry sink.</param> /// <unmanaged>void SetSegmentFlags([None] D2D1_PATH_SEGMENT vertexFlags)</unmanaged> /// <remarks> /// After this method is called, the specified segment flags are applied to each segment subsequently added to the sink. The segment flags are applied to every additional segment until this method is called again and a different set of segment flags is specified. /// </remarks> public void SetSegmentFlags(PathSegment vertexFlags) { m_currentPathSegment = vertexFlags; }
public void VisitSegment(PathSegment node, GlobVisitorContext context) { if (node.IsIdentifier) { // Get the (relative) path to the current node. var segment = node.GetPath(); // Get a directory that matches this segment. // This might be a file but we can't be sure so we need to check. var directoryPath = context.Path.Combine(segment); var directory = context.FileSystem.GetDirectory(directoryPath); // Should we not traverse this directory? if (directory.Exists && !context.ShouldTraverse(directory)) { return; } if (node.Next == null) { if (directory.Exists) { // Directory context.AddResult(directory); } else { // Then it must be a file (if it exist). var filePath = context.Path.CombineWithFilePath(segment); var file = context.FileSystem.GetFile(filePath); if (file.Exists) { // File context.AddResult(file); } } } else { // Push the current node to the context. context.Push(node.GetPath()); node.Next.Accept(this, context); context.Pop(); } } else { if (node.Tokens.Count > 1) { var path = context.FileSystem.GetDirectory(context.Path); if (path.Exists) { foreach (var candidate in FindCandidates(path.Path, node, context, SearchScope.Current)) { if (node.Next != null) { context.Push(candidate.Path.FullPath.Substring(path.Path.FullPath.Length + 1)); node.Next.Accept(this, context); context.Pop(); } else { context.AddResult(candidate); } } } } } }
/// <summary> /// Adds a path segment to the forward queue. /// </summary> /// <param name="segment"></param> public void AddForward(PathSegment<long> segment) { _forward[segment.VertexId] = segment; PathSegment<long> backward; if (_backward.TryGetValue(segment.VertexId, out backward)) { _intersection.Add(segment.VertexId, backward.Weight + segment.Weight); } }
public static PathSegment ApplyTransform(PathSegment segment, Point start, GeneralTransform transform) { return(PathSegmentImplementation.Create(segment, start).ApplyTransform(transform)); }
/// <summary> /// Used by the <see cref="ActionModelNode.CloneTree"/> method. /// </summary> /// <remarks> /// Derived classes must override this method to return a clone node. This clone should /// not copy the sub-tree. /// </remarks> /// <param name="pathSegment">The path segment which this node represents.</param> /// <returns>A new node of this type.</returns> protected override ActionModelNode CloneNode(PathSegment pathSegment) { return new SeparatorNode(pathSegment); }
public static void FlattenSegment(this PathSegment segment, IList <Point> points, Point start, double tolerance) { PathSegmentImplementation.Create(segment, start).Flatten(points, tolerance); }
/// <summary> /// Used by the <see cref="CloneTree"/> method. /// </summary> /// <remarks> /// Derived classes must override this method to return a clone node. This clone should /// not copy the sub-tree. /// </remarks> /// <param name="pathSegment">The path segment which this node represents.</param> /// <returns>A new node of this type.</returns> protected abstract ActionModelNode CloneNode(PathSegment pathSegment);
public static Point GetLastPoint(this PathSegment segment) { return(segment.GetPoint(-1)); }
private readonly IAction _action; // null if this is not a leaf node /// <summary> /// Constructor /// </summary> /// <param name="pathSegment"></param> /// <param name="action"></param> protected internal ActionNode(PathSegment pathSegment, IAction action) : base(pathSegment) { _action = action; }
public static Point GetPoint(this PathSegment segment, int index) { return(PathSegmentImplementation.Create(segment).GetPoint(index)); }
/// <summary> /// Constructor /// </summary> /// <param name="pathSegment"></param> protected internal BranchNode(PathSegment pathSegment) : base(pathSegment) { }
public static IEnumerable <SimpleSegment> GetSimpleSegments(this PathSegment segment, Point start) { return(PathSegmentImplementation.Create(segment, start).GetSimpleSegments()); }
void SimplifiedGeometrySink.SetSegmentFlags(PathSegment vertexFlags) { }
public static bool IsEmpty(this PathSegment segment) { return(segment.GetPointCount() == 0); }
private Expression ParseChainedExpression(string resourceType, SearchParameter searchParameter, PathSegment[] paths, int currentIndex, string value) { Debug.Assert( currentIndex >= 0 && currentIndex < paths.Length, $"The {nameof(currentIndex)} is invalid."); PathSegment path = paths[currentIndex]; string currentPath = path.Path; string targetResourceType = path.ModifierOrResourceType; // We have more paths after this so this is a chained expression. // Since this is chained expression, the expression must be a reference type. if (searchParameter.Type != SearchParamType.Reference) { // The search parameter is not a reference type, which is not allowed. throw new InvalidSearchOperationException(Core.Resources.ChainedParameterMustBeReferenceSearchParamType); } ResourceType?scopedTargetResourceType = null; // Check to see if the client has specifically specified the target resource type to scope to. if (targetResourceType != null) { // A target resource type is specified. if (!Enum.TryParse(targetResourceType, out ResourceType parsedResourceType)) { throw new InvalidSearchOperationException(string.Format(Core.Resources.ResourceNotSupported, resourceType)); } scopedTargetResourceType = parsedResourceType; } // If the scoped target resource type is specified, we will scope to that; otherwise, all target resource types are considered. ChainedExpression[] chainedExpressions = searchParameter.Target .Where(targetType => targetType != null && (scopedTargetResourceType ?? targetType) == targetType) .Select(targetType => { try { return(Expression.Chained( resourceType, currentPath, targetType.Value.ToString(), Parse( targetType.Value.ToString(), paths, currentIndex + 1, value))); } catch (Exception ex) when(ex is ResourceNotSupportedException || ex is SearchParameterNotSupportedException) { // The resource or search parameter is not supported for the resource. // We will ignore these unsupported types. return(null); } }) .Where(item => item != null) .ToArray(); if (!chainedExpressions.Any()) { // There was no reference that supports the search parameter. throw new InvalidSearchOperationException(Core.Resources.ChainedParameterNotSupported); } return(Expression.Or(chainedExpressions)); }
internal void InitializePathSegments(DataServiceProviderWrapper provider) { if (this.pathSegments == null) { string[] strArray = this.pathExpression.Split(new char[] { '/' }); ResourceType parameterType = this.bindingParameter.ParameterType; if (parameterType.ResourceTypeKind == ResourceTypeKind.EntityCollection) { parameterType = ((EntityCollectionResourceType) this.bindingParameter.ParameterType).ItemType; } List<PathSegment> list = new List<PathSegment>(); PathSegment item = new PathSegment { SourceType = parameterType }; bool flag = false; int length = strArray.Length; if (length == 1) { list.Add(item); } else { for (int i = 1; i < length; i++) { string str = strArray[i]; if (string.IsNullOrEmpty(str)) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_EmptySegment(this.pathExpression)); } ResourceProperty property = item.SourceType.TryResolvePropertyName(str); if (property == null) { bool previousSegmentIsTypeSegment = flag; ResourceType type2 = WebUtil.ResolveTypeIdentifier(provider, str, item.SourceType, previousSegmentIsTypeSegment); if (type2 == null) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PropertyNotFound(this.pathExpression, str, item.SourceType.FullName)); } item.SourceType = type2; flag = true; if (i == (length - 1)) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PathCannotEndWithTypeIdentifier(this.pathExpression, strArray[length - 1])); } } else { flag = false; item.Property = property; list.Add(item); item = new PathSegment { SourceType = property.ResourceType }; } if (item.SourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PropertyMustBeEntityType(this.pathExpression, str, item.SourceType.FullName)); } } } this.pathSegments = list.ToArray(); } }
public void Test_Constructor_EmptyLocalized() { var p = new PathSegment("a", ""); Assert.AreEqual("a", p.ResourceKey); Assert.AreEqual("", p.LocalizedText); }
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Debug.Assert(values != null && values.Length == 9, "EdgeRouteToPathConverter should have 9 parameters: pos (1,2), size (3,4) of source; pos (5,6), size (7,8) of target; routeInformation (9)."); #region Get the inputs //get the position of the source Point sourcePos = new Point() { X = (values[0] != DependencyProperty.UnsetValue ? (double)values[0] : 0.0), Y = (values[1] != DependencyProperty.UnsetValue ? (double)values[1] : 0.0) }; //get the size of the source Size sourceSize = new Size() { Width = (values[2] != DependencyProperty.UnsetValue ? (double)values[2] : 0.0), Height = (values[3] != DependencyProperty.UnsetValue ? (double)values[3] : 0.0) }; //get the position of the target Point targetPos = new Point() { X = (values[4] != DependencyProperty.UnsetValue ? (double)values[4] : 0.0), Y = (values[5] != DependencyProperty.UnsetValue ? (double)values[5] : 0.0) }; //get the size of the target Size targetSize = new Size() { Width = (values[6] != DependencyProperty.UnsetValue ? (double)values[6] : 0.0), Height = (values[7] != DependencyProperty.UnsetValue ? (double)values[7] : 0.0) }; //get the route informations Point[] routeInformation = (values[8] != DependencyProperty.UnsetValue ? (Point[])values[8] : null); #endregion bool hasRouteInfo = routeInformation != null && routeInformation.Length > 0; // // Create the path // Point p1 = GraphConverterHelper.CalculateAttachPoint(sourcePos, sourceSize, (hasRouteInfo ? routeInformation[0] : targetPos)); Point p2 = GraphConverterHelper.CalculateAttachPoint(targetPos, targetSize, (hasRouteInfo ? routeInformation[routeInformation.Length - 1] : sourcePos)); PathSegment[] segments = new PathSegment[1 + (hasRouteInfo ? routeInformation.Length : 0)]; if (hasRouteInfo) { //append route points for (int i = 0; i < routeInformation.Length; i++) { segments[i] = new LineSegment(routeInformation[i], true); } } Point pLast = (hasRouteInfo ? routeInformation[routeInformation.Length - 1] : p1); Vector v = pLast - p2; v = v / v.Length * 5; Vector n = new Vector(-v.Y, v.X) * 0.3; segments[segments.Length - 1] = new LineSegment(p2 + v, true); PathFigureCollection pfc = new PathFigureCollection(2); pfc.Add(new PathFigure(p1, segments, false)); pfc.Add(new PathFigure(p2, new PathSegment[] { new LineSegment(p2 + v - n, true), new LineSegment(p2 + v + n, true) }, true)); return(pfc); }
/// <summary> /// Sets the binding resource type for the current path expression. /// </summary> /// <param name="provider">Provider wrapper instance.</param> internal void InitializePathSegments(DataServiceProviderWrapper provider) { Debug.Assert(this.bindingParameter != null, "this.bindingResourceType != null"); if (this.pathSegments == null) { string[] segmentStrings = this.pathExpression.Split(PathSeparator); Debug.Assert(segmentStrings[0] == this.bindingParameter.Name, "segmentStrings[0] == this.bindingParameter.Name"); ResourceType bindingType = this.bindingParameter.ParameterType; if (bindingType.ResourceTypeKind == ResourceTypeKind.EntityCollection) { bindingType = ((EntityCollectionResourceType)this.bindingParameter.ParameterType).ItemType; } List<PathSegment> segmentList = new List<PathSegment>(); PathSegment currentSegment = new PathSegment { SourceType = bindingType }; bool seenTypeSegment = false; int segmentLength = segmentStrings.Length; if (segmentLength == 1) { segmentList.Add(currentSegment); } else { for (int idx = 1; idx < segmentLength; idx++) { string segmentString = segmentStrings[idx]; if (string.IsNullOrEmpty(segmentString)) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_EmptySegment(this.pathExpression)); } ResourceProperty currentProperty = currentSegment.SourceType.TryResolvePropertyName(segmentString); if (currentProperty == null) { ResourceType currentType = WebUtil.ResolveTypeIdentifier(provider, segmentString, currentSegment.SourceType, previousSegmentIsTypeSegment: seenTypeSegment); if (currentType != null) { currentSegment.SourceType = currentType; seenTypeSegment = true; if (idx == segmentLength - 1) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PathCannotEndWithTypeIdentifier(this.pathExpression, segmentStrings[segmentLength - 1])); } } else { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PropertyNotFound(this.pathExpression, segmentString, currentSegment.SourceType.FullName)); } } else { seenTypeSegment = false; currentSegment.Property = currentProperty; segmentList.Add(currentSegment); currentSegment = new PathSegment { SourceType = currentProperty.ResourceType }; } if (currentSegment.SourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { throw new InvalidOperationException(Strings.ResourceSetPathExpression_PropertyMustBeEntityType(this.pathExpression, segmentString, currentSegment.SourceType.FullName)); } } } this.pathSegments = segmentList.ToArray(); } }