static internal Point SegmentIntersection(Point first, Point second, Point from) { Directions dir = PointComparer.GetPureDirection(first, second); Point intersect = IsVertical(dir) ? new Point(first.X, from.Y) : new Point(from.X, first.Y); return(intersect); }
internal static bool FindBracketingVertices(VisibilityVertex sourceVertex, Point targetPoint, Directions dirToTarget , out VisibilityVertex bracketSource, out VisibilityVertex bracketTarget) { // Walk from the source to target until we bracket target or there is no nextVertex // in the desired direction. bracketSource = sourceVertex; for (; ;) { bracketTarget = StaticGraphUtility.FindNextVertex(bracketSource, dirToTarget); if (null == bracketTarget) { break; } if (PointComparer.Equal(bracketTarget.Point, targetPoint)) { // Desired edge already exists. return(true); } if (dirToTarget != PointComparer.GetPureDirection(bracketTarget.Point, targetPoint)) { // bracketTarget is past vertex in the traversal direction. break; } bracketSource = bracketTarget; } return(null != bracketTarget); }
private static VisibilityVertex GetSpliceTarget(ref VisibilityVertex spliceSource, Directions spliceTargetDir, Point nextExtendPoint) { // Look for the target. There may be a dead-ended edge starting at the current spliceSource // edge that has a vertex closer to the extension line; in that case keep walking until we // have the closest vertex on the Source side of the extension line as spliceSource. Directions prevDir = PointComparer.GetPureDirection(spliceSource.Point, nextExtendPoint); Directions nextDir = prevDir; var spliceTarget = spliceSource; while (nextDir == prevDir) { spliceSource = spliceTarget; spliceTarget = StaticGraphUtility.FindNextVertex(spliceSource, spliceTargetDir); if (null == spliceTarget) { break; } if (PointComparer.Equal(spliceTarget.Point, nextExtendPoint)) { // If we encountered an existing vertex for the extension chain, update spliceTarget // to be after it and we're done with this loop. spliceTarget = StaticGraphUtility.FindNextVertex(spliceTarget, spliceTargetDir); break; } nextDir = PointComparer.GetPureDirection(spliceTarget.Point, nextExtendPoint); } return(spliceTarget); }
void DevTrace_VerifyVertex(VisibilityVertex vertex) { if (transGraphVerify.IsLevel(1)) { Directions dir = Directions.North; for (int idir = 0; idir < 4; ++idir, dir = CompassVector.RotateRight(dir)) { int count = 0; int cEdges = vertex.InEdges.Count; // indexing is faster than foreach for Lists for (int ii = 0; ii < cEdges; ++ii) { var edge = vertex.InEdges[ii]; if (PointComparer.GetPureDirection(vertex.Point, edge.SourcePoint) == dir) { ++count; } } // Avoid GetEnumerator overhead. var outEdgeNode = vertex.OutEdges.IsEmpty() ? null : vertex.OutEdges.TreeMinimum(); for (; outEdgeNode != null; outEdgeNode = vertex.OutEdges.Next(outEdgeNode)) { var edge = outEdgeNode.Item; if (PointComparer.GetPureDirection(vertex.Point, edge.TargetPoint) == dir) { ++count; } } Debug.Assert(count < 2, "vertex has multiple edges in one direction"); } } }
static internal VisibilityVertex FindNextVertex(VisibilityVertex vertex, Directions dir) { // This function finds the next vertex in the desired direction relative to the // current vertex, not necessarily the edge orientation, hence it does not use // EdgeDirection(). This is so the caller can operate on a desired movement // direction without having to track whether we're going forward or backward // through the In/OutEdge chain. int cEdges = vertex.InEdges.Count; // indexing is faster than foreach for Lists for (int ii = 0; ii < cEdges; ++ii) { var edge = vertex.InEdges[ii]; if (PointComparer.GetPureDirection(vertex.Point, edge.SourcePoint) == dir) { return(edge.Source); } } // Avoid GetEnumerator overhead. var outEdgeNode = vertex.OutEdges.IsEmpty() ? null : vertex.OutEdges.TreeMinimum(); for (; outEdgeNode != null; outEdgeNode = vertex.OutEdges.Next(outEdgeNode)) { var edge = outEdgeNode.Item; if (PointComparer.GetPureDirection(vertex.Point, edge.TargetPoint) == dir) { return(edge.Target); } } return(null); }
private void AddGroupIntersectionsToRestrictedRay(Obstacle obstacle, IList <IntersectionInfo> intersections) { // We'll let the lines punch through any intersections with groups, but track the location so we can enable/disable crossing. foreach (var intersectionInfo in intersections) { var intersect = SpliceUtility.RawIntersection(intersectionInfo, currentRestrictedRay.Start); // Skip intersections that are past the end of the restricted segment (though there may still be some // there if we shorten it later, but we'll skip them later). var distSquared = (intersect - currentRestrictedRay.Start).LengthSquared; if (distSquared > restrictedRayLengthSquared) { continue; } var dirTowardIntersect = PointComparer.GetPureDirection(currentRestrictedRay.Start, currentRestrictedRay.End); var polyline = (Polyline)intersectionInfo.Segment1; // this is the second arg to GetAllIntersections var dirsOfSide = CompassVector.VectorDirection(polyline.Derivative(intersectionInfo.Par1)); // The derivative is always clockwise, so if the side contains the rightward rotation of the // direction from the ray origin, then we're hitting it from the inside; otherwise from the outside. var dirToInsideOfGroup = dirTowardIntersect; if (0 != (dirsOfSide & CompassVector.RotateRight(dirTowardIntersect))) { dirToInsideOfGroup = CompassVector.OppositeDir(dirToInsideOfGroup); } CurrentGroupBoundaryCrossingMap.AddIntersection(intersect, obstacle, dirToInsideOfGroup); } }
// ctor internal void Update(Point start, Point end) { Debug.Assert(PointComparer.Equal(start, end) || StaticGraphUtility.IsAscending(PointComparer.GetPureDirection(start, end)) , "non-ascending segment"); startPoint = start; endPoint = end; }
private void SpliceGroupBoundaryCrossings(PointAndCrossingsList crossingList, VisibilityVertex startVertex, LineSegment maxSegment) { if ((null == crossingList) || (0 == crossingList.Count)) { return; } crossingList.Reset(); var start = maxSegment.Start; var end = maxSegment.End; var dir = PointComparer.GetPureDirection(start, end); // Make sure we are going in the ascending direction. if (!StaticGraphUtility.IsAscending(dir)) { start = maxSegment.End; end = maxSegment.Start; dir = CompassVector.OppositeDir(dir); } // We need to back up to handle group crossings that are between a VisibilityBorderIntersect on a sloped border and the // incoming startVertex (which is on the first ScanSegment in Perpendicular(dir) that is outside that padded border). startVertex = TraverseToFirstVertexAtOrAbove(startVertex, start, CompassVector.OppositeDir(dir)); // Splice into the Vertices between and including the start/end points. for (var currentVertex = startVertex; null != currentVertex; currentVertex = StaticGraphUtility.FindNextVertex(currentVertex, dir)) { bool isFinalVertex = (PointComparer.Compare(currentVertex.Point, end) >= 0); while (crossingList.CurrentIsBeforeOrAt(currentVertex.Point)) { PointAndCrossings pac = crossingList.Pop(); // If it's past the start and at or before the end, splice in the crossings in the descending direction. if (PointComparer.Compare(pac.Location, startVertex.Point) > 0) { if (PointComparer.Compare(pac.Location, end) <= 0) { SpliceGroupBoundaryCrossing(currentVertex, pac, CompassVector.OppositeDir(dir)); } } // If it's at or past the start and before the end, splice in the crossings in the descending direction. if (PointComparer.Compare(pac.Location, startVertex.Point) >= 0) { if (PointComparer.Compare(pac.Location, end) < 0) { SpliceGroupBoundaryCrossing(currentVertex, pac, dir); } } } if (isFinalVertex) { break; } } }
private void GetRestrictedIntersectionTestSegment(Point startPoint, Point endPoint) { // Due to rounding issues use a larger line span for intersection calculations. Directions segDir = PointComparer.GetPureDirection(startPoint, endPoint); double startX = (Directions.West == segDir) ? GraphBox.Right : ((Directions.East == segDir) ? GraphBox.Left : startPoint.X); double endX = (Directions.West == segDir) ? GraphBox.Left : ((Directions.East == segDir) ? GraphBox.Right : endPoint.X); double startY = (Directions.South == segDir) ? GraphBox.Top * 2: ((Directions.North == segDir) ? GraphBox.Bottom : startPoint.Y); double endY = (Directions.South == segDir) ? GraphBox.Bottom : ((Directions.North == segDir) ? GraphBox.Top : startPoint.Y); restrictedIntersectionTestSegment = new LineSegment(new Point(startX, startY), new Point(endX, endY)); }
private void ExtendEdgeChain(VisibilityVertex startVertex, Directions extendDir , LineSegment maxDesiredSegment, LineSegment maxVisibilitySegment , PointAndCrossingsList pacList, bool isOverlapped) { StaticGraphUtility.Assert(PointComparer.GetPureDirection(maxDesiredSegment.Start, maxDesiredSegment.End) == extendDir , "maxDesiredSegment is reversed", ObstacleTree, VisGraph); // Direction*s*, because it may return None, which is valid and means startVertex is on the // border of an obstacle and we don't want to go inside it. Directions segmentDir = PointComparer.GetDirections(startVertex.Point, maxDesiredSegment.End); if (segmentDir != extendDir) { // OppositeDir may happen on overlaps where the boundary has a gap in its ScanSegments due to other obstacles // overlapping it and each other. This works because the port has an edge connected to startVertex, // which is on a ScanSegment outside the obstacle. StaticGraphUtility.Assert(isOverlapped || (segmentDir != CompassVector.OppositeDir(extendDir)) , "obstacle encountered between prevPoint and startVertex", ObstacleTree, VisGraph); return; } // We'll find the segment to the left (or right if to the left doesn't exist), // then splice across in the opposite direction. Directions spliceSourceDir = CompassVector.RotateLeft(extendDir); VisibilityVertex spliceSource = StaticGraphUtility.FindNextVertex(startVertex, spliceSourceDir); if (null == spliceSource) { spliceSourceDir = CompassVector.OppositeDir(spliceSourceDir); spliceSource = StaticGraphUtility.FindNextVertex(startVertex, spliceSourceDir); if (null == spliceSource) { return; } } // Store this off before ExtendSpliceWorker, which overwrites it. Directions spliceTargetDir = CompassVector.OppositeDir(spliceSourceDir); VisibilityVertex spliceTarget; if (ExtendSpliceWorker(spliceSource, extendDir, spliceTargetDir, maxDesiredSegment, maxVisibilitySegment, isOverlapped, out spliceTarget)) { // We ended on the source side and may have dead-ends on the target side so reverse sides. ExtendSpliceWorker(spliceTarget, extendDir, spliceSourceDir, maxDesiredSegment, maxVisibilitySegment, isOverlapped, out spliceTarget); } SpliceGroupBoundaryCrossings(pacList, startVertex, maxDesiredSegment); }
internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight) { // Since we're adding transient edges into the graph, we're not doing full intersection // evaluation; thus there may already be an edge from the source vertex in the direction // of the target vertex, but ending before or after the target vertex. Directions dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex); VisibilityVertex bracketSource, bracketTarget; // Is there an edge in the chain from sourceVertex in the direction of targetVertex // that brackets targetvertex? // <sourceVertex> -> ..1.. -> ..2.. <end> 3 // Yes if targetVertex is at the x above 1 or 2, No if it is at 3. If false, bracketSource // will be set to the vertex at <end> (if there are any edges in that direction at all). VisibilityVertex splitVertex = targetVertex; if (!FindBracketingVertices(sourceVertex, targetVertex.Point, dirToTarget , out bracketSource, out bracketTarget)) { // No bracketing of targetVertex from sourceVertex but bracketSource has been updated. // Is there a bracket of bracketSource from the targetVertex direction? // 3 <end> ..2.. <- ..1.. <targetVertex> // Yes if bracketSource is at the x above 1 or 2, No if it is at 3. If false, bracketTarget // will be set to the vertex at <end> (if there are any edges in that direction at all). // If true, then bracketSource and splitVertex must be updated. VisibilityVertex tempSource; if (FindBracketingVertices(targetVertex, sourceVertex.Point, CompassVector.OppositeDir(dirToTarget) , out bracketTarget, out tempSource)) { Debug.Assert(bracketSource == sourceVertex, "Mismatched bracketing detection"); bracketSource = tempSource; splitVertex = sourceVertex; } } // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the // first half-edge (and weight is ignored as the split uses the edge weight). var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point); edge = (null != edge) ? this.SplitEdge(edge, splitVertex) : CreateEdge(bracketSource, bracketTarget, weight); DevTrace_VerifyEdge(edge); return(edge); }
internal void ExtendEdgeChain(VisibilityVertex startVertex, Rectangle limitRect, LineSegment maxVisibilitySegment, PointAndCrossingsList pacList, bool isOverlapped) { var dir = PointComparer.GetDirections(maxVisibilitySegment.Start, maxVisibilitySegment.End); if (dir == Directions.None) { return; } Debug.Assert(CompassVector.IsPureDirection(dir), "impure max visibility segment"); // Shoot the edge chain out to the shorter of max visibility or intersection with the limitrect. StaticGraphUtility.Assert(PointComparer.Equal(maxVisibilitySegment.Start, startVertex.Point) || (PointComparer.GetPureDirection(maxVisibilitySegment.Start, startVertex.Point) == dir) , "Inconsistent direction found", ObstacleTree, VisGraph); double oppositeFarBound = StaticGraphUtility.GetRectangleBound(limitRect, dir); Point maxDesiredSplicePoint = StaticGraphUtility.IsVertical(dir) ? ApproximateComparer.Round(new Point(startVertex.Point.X, oppositeFarBound)) : ApproximateComparer.Round(new Point(oppositeFarBound, startVertex.Point.Y)); if (PointComparer.Equal(maxDesiredSplicePoint, startVertex.Point)) { // Nothing to do. return; } if (PointComparer.GetPureDirection(startVertex.Point, maxDesiredSplicePoint) != dir) { // It's in the opposite direction, so no need to do anything. return; } // If maxDesiredSplicePoint is shorter, create a new shorter segment. We have to pass both segments // through to the worker function so it knows whether it can go past maxDesiredSegment (which may be limited // by limitRect). var maxDesiredSegment = maxVisibilitySegment; if (PointComparer.GetDirections(maxDesiredSplicePoint, maxDesiredSegment.End) == dir) { maxDesiredSegment = new LineSegment(maxDesiredSegment.Start, maxDesiredSplicePoint); } ExtendEdgeChain(startVertex, dir, maxDesiredSegment, maxVisibilitySegment, pacList, isOverlapped); }
static internal VisibilityEdge FindAdjacentEdge(VisibilityVertex a, Direction dir) { foreach (var edge in a.InEdges) { if (PointComparer.GetPureDirection(edge.SourcePoint, a.Point) == dir) { return(edge); } } foreach (var edge in a.OutEdges) { if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir) { return(edge); } } return(null); }
internal void AddToAdjacentVertex(TransientGraphUtility transUtil, VisibilityVertex targetVertex , Rectangle limitRect, bool routeToCenter) { VisibilityVertex borderVertex = transUtil.VisGraph.FindVertex(this.VisibilityBorderIntersect); if (null != borderVertex) { ExtendFromBorderVertex(transUtil, borderVertex, limitRect, routeToCenter); return; } // There is no vertex at VisibilityBorderIntersect, so create it and link it to targetVertex. // Note: VisibilityBorderIntersect may == targetIntersect if that is on our border, *and* // targetIntersect may be on the border of a touching obstacle, in which case this will splice // into or across the adjacent obstacle, which is consistent with "touching is overlapped". // So we don't use UnpaddedBorderIntersect as prevPoint when calling ExtendEdgeChain. // VisibilityBorderIntersect may be rounded just one Curve.DistanceEpsilon beyond the ScanSegment's // perpendicular coordinate; e.g. our X may be targetIntersect.X + Curve.DistanceEpsilon, thereby // causing the direction from VisibilityBorderIntersect to targetIntersect to be W instead of E. // So use the targetIntersect if they are close enough; they will be equal for flat borders, and // otherwise the exact value we use only needs be "close enough" to the border. (We can't use // CenterVertex as the prevPoint because that could be an impure direction). // Update: With the change to carry MaxVisibilitySegment within the PortEntrance, PortManager finds // targetVertex between VisibilityBorderIntersect and MaxVisibilitySegment.End, so this should no longer // be able to happen. // See RectilinearTests.PaddedBorderIntersectMeetsIncomingScanSegment for an example of what happens // when VisibilityBorderIntersect is on the incoming ScanSegment (it jumps out above with borderVertex found). if (OutwardDirection == PointComparer.GetPureDirection(targetVertex.Point, this.VisibilityBorderIntersect)) { Debug.Assert(false, "Unexpected reversed direction between VisibilityBorderIntersect and targetVertex"); // ReSharper disable HeuristicUnreachableCode this.VisibilityBorderIntersect = targetVertex.Point; borderVertex = targetVertex; // ReSharper restore HeuristicUnreachableCode } else { borderVertex = transUtil.FindOrAddVertex(this.VisibilityBorderIntersect); transUtil.FindOrAddEdge(borderVertex, targetVertex, InitialWeight); } ExtendEdgeChain(transUtil, borderVertex, targetVertex, limitRect, routeToCenter); }
internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight) { // Since we're adding transient edges into the graph, we're not doing full intersection // evaluation; thus there may already be an edge from the source vertex in the direction // of the target vertex, but ending before or after the target vertex. Direction dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex); VisibilityVertex bracketSource, bracketTarget, splitVertex; GetBrackets(sourceVertex, targetVertex, dirToTarget, out bracketSource, out bracketTarget, out splitVertex); // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the // first half-edge (and weight is ignored as the split uses the edge weight). var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point); edge = (edge != null) ? this.SplitEdge(edge, splitVertex) : CreateEdge(bracketSource, bracketTarget, weight); DevTrace_VerifyEdge(edge); return(edge); }
internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect) { // Extend the edge chain to the opposite side of the limit rectangle. StaticGraphUtility.Assert(PointComparer.Equal(this.Point, targetVertex.Point) || (PointComparer.GetPureDirection(this.Point, targetVertex.Point) == dirToExtend) , "input dir does not match with to-targetVertex direction", transUtil.ObstacleTree, transUtil.VisGraph); var extendOverlapped = IsOverlapped; if (extendOverlapped) { // The initial vertex we connected to may be on the border of the enclosing obstacle, // or of another also-overlapped obstacle. If the former, we turn off overlap now. extendOverlapped = transUtil.ObstacleTree.PointIsInsideAnObstacle(targetVertex.Point, dirToExtend); } // If we're inside an obstacle's boundaries we'll never extend past the end of the obstacle // due to encountering the boundary from the inside. So start the extension at targetVertex. SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.IsOverlapped ? targetVertex : this.Vertex, dirToExtend, transUtil); transUtil.ExtendEdgeChain(targetVertex, limitRect, segmentAndCrossings.Item1, segmentAndCrossings.Item2, extendOverlapped); }
static internal VisibilityVertex FindAdjacentVertex(VisibilityVertex a, Direction dir) { // This function finds the next vertex in the desired direction relative to the // current vertex, not necessarily the edge orientation, hence it does not use // EdgeDirection(). This is so the caller can operate on a desired movement // direction without having to track whether we're going forward or backward // through the In/OutEdge chain. foreach (var edge in a.InEdges) { if (PointComparer.GetPureDirection(a.Point, edge.SourcePoint) == dir) { return(edge.Source); } } foreach (var edge in a.OutEdges) { if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir) { return(edge.Target); } } return(null); }
// The return value is whether we should try a second pass if this is called on the first pass, // using spliceTarget to wrap up dead-ends on the target side. bool ExtendSpliceWorker(VisibilityVertex spliceSource, Directions extendDir, Directions spliceTargetDir , LineSegment maxDesiredSegment, LineSegment maxVisibilitySegment , bool isOverlapped, out VisibilityVertex spliceTarget) { // This is called after having created at least one extension vertex (initially, the // first one added outside the obstacle), so we know extendVertex will be there. spliceSource // is the vertex to the OppositeDir(spliceTargetDir) of that extendVertex. VisibilityVertex extendVertex = StaticGraphUtility.FindNextVertex(spliceSource, spliceTargetDir); spliceTarget = StaticGraphUtility.FindNextVertex(extendVertex, spliceTargetDir); for (; ;) { if (!GetNextSpliceSource(ref spliceSource, spliceTargetDir, extendDir)) { break; } // spliceSource is now on the correct edge relative to the desired nextExtendPoint. // spliceTarget is in the opposite direction of the extension-line-to-spliceSource. Point nextExtendPoint = StaticGraphUtility.FindBendPointBetween(extendVertex.Point , spliceSource.Point, CompassVector.OppositeDir(spliceTargetDir)); // We test below for being on or past maxDesiredSegment; here we may be skipping // over maxDesiredSegmentEnd which is valid since we want to be sure to go to or // past limitRect, but be sure to stay within maxVisibilitySegment. if (IsPointPastSegmentEnd(maxVisibilitySegment, nextExtendPoint)) { break; } spliceTarget = GetSpliceTarget(ref spliceSource, spliceTargetDir, nextExtendPoint); //StaticGraphUtility.Test_DumpVisibilityGraph(ObstacleTree, VisGraph); if (null == spliceTarget) { // This may be because spliceSource was created just for Group boundaries. If so, // skip to the next nextExtendVertex location. if (this.IsSkippableSpliceSourceWithNullSpliceTarget(spliceSource, extendDir)) { continue; } // We're at a dead-end extending from the source side, or there is an intervening obstacle, or both. // Don't splice across lateral group boundaries. if (ObstacleTree.SegmentCrossesAnObstacle(spliceSource.Point, nextExtendPoint)) { return(false); } } // We might be walking through a point where a previous chain dead-ended. VisibilityVertex nextExtendVertex = VisGraph.FindVertex(nextExtendPoint); if (null != nextExtendVertex) { if ((null == spliceTarget) || (null != this.VisGraph.FindEdge(extendVertex.Point, nextExtendPoint))) { // We are probably along a ScanSegment so visibility in this direction has already been determined. // Stop and don't try to continue extension from the opposite side. If we continue splicing here // it might go across an obstacle. if (null == spliceTarget) { Debug_VerifyNonOverlappedExtension(isOverlapped, extendVertex, nextExtendVertex, spliceSource: null, spliceTarget: null); FindOrAddEdge(extendVertex, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight); } return(false); } // This should always have been found in the find-the-next-target loop above if there is // a vertex (which would be nextExtendVertex, which we just found) between spliceSource // and spliceTarget. Even for a sparse graph, an edge should not skip over a vertex. StaticGraphUtility.Assert(spliceTarget == StaticGraphUtility.FindNextVertex(nextExtendVertex, spliceTargetDir) , "no edge exists between an existing nextExtendVertex and spliceTarget" , ObstacleTree, VisGraph); } else { StaticGraphUtility.Assert((null == spliceTarget) || spliceTargetDir == PointComparer.GetPureDirection(nextExtendPoint, spliceTarget.Point) , "spliceTarget is not to spliceTargetDir of nextExtendVertex" , ObstacleTree, VisGraph); nextExtendVertex = this.AddVertex(nextExtendPoint); } FindOrAddEdge(extendVertex, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight); Debug_VerifyNonOverlappedExtension(isOverlapped, extendVertex, nextExtendVertex, spliceSource, spliceTarget); // This will split the edge if targetVertex is non-null; otherwise we are at a dead-end // on the target side so must not create a vertex as it would be inside an obstacle. FindOrAddEdge(spliceSource, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight); if (isOverlapped) { isOverlapped = this.SeeIfSpliceIsStillOverlapped(extendDir, nextExtendVertex); } extendVertex = nextExtendVertex; // Test GetDirections because it may return Directions. None. if (0 == (extendDir & PointComparer.GetDirections(nextExtendPoint, maxDesiredSegment.End))) { // At or past the desired max extension point, so we're done. spliceTarget = null; break; } } return(null != spliceTarget); }
static internal bool PointIsOnSegment(Point first, Point second, Point test) { return(PointComparer.Equal(first, test) || PointComparer.Equal(second, test) || (PointComparer.GetPureDirection(first, test) == PointComparer.GetPureDirection(test, second))); }
static internal bool IsVertical(VisibilityEdge edge) { return(IsVertical(PointComparer.GetPureDirection(edge.SourcePoint, edge.TargetPoint))); }
static internal bool IsVertical(Point first, Point second) { return(IsVertical(PointComparer.GetPureDirection(first, second))); }
static internal Directions EdgeDirection(VisibilityVertex source, VisibilityVertex target) { return(PointComparer.GetPureDirection(source.Point, target.Point)); }
static internal bool IsVertical(LineSegment seg) { return(IsVertical(PointComparer.GetPureDirection(seg.Start, seg.End))); }