void ProcessRightIntersectionEvent(RightIntersectionEvent rightIntersectionEvent) { //restore Z for the time being // Z = PreviousZ; if (rightIntersectionEvent.coneRightSide.Removed == false) { //it can happen that the cone side participating in the intersection is gone; //obstracted by another obstacle or because of a vertex found inside of the cone //PrintOutRightSegTree(); RemoveSegFromRightTree(rightIntersectionEvent.coneRightSide); Z = SweepDirection * rightIntersectionEvent.Site; var rightSide = new BrokenConeSide( rightIntersectionEvent.Site, rightIntersectionEvent.EndVertex, rightIntersectionEvent.coneRightSide); InsertToTree(rightConeSides, rightSide); rightIntersectionEvent.coneRightSide.Cone.RightSide = rightSide; LookForIntersectionOfObstacleSideAndRightConeSide(rightIntersectionEvent.Site, rightIntersectionEvent.EndVertex); TryCreateConeClosureForRightSide(rightSide); } else { Z = SweepDirection * rightIntersectionEvent.Site; } }
void ProcessLeftIntersectionEvent(LeftIntersectionEvent leftIntersectionEvent) { if (leftIntersectionEvent.coneLeftSide.Removed == false) { if (Math.Abs((leftIntersectionEvent.EndVertex.Point - leftIntersectionEvent.Site) * SweepDirection) < ApproximateComparer.DistanceEpsilon) { //the cone is totally covered by a horizontal segment RemoveCone(leftIntersectionEvent.coneLeftSide.Cone); } else { RemoveSegFromLeftTree(leftIntersectionEvent.coneLeftSide); Z = SweepDirection * leftIntersectionEvent.Site; //it is safe now to restore the order var leftSide = new BrokenConeSide( leftIntersectionEvent.Site, leftIntersectionEvent.EndVertex, leftIntersectionEvent.coneLeftSide); InsertToTree(leftConeSides, leftSide); leftIntersectionEvent.coneLeftSide.Cone.LeftSide = leftSide; LookForIntersectionOfObstacleSideAndLeftConeSide(leftIntersectionEvent.Site, leftIntersectionEvent.EndVertex); TryCreateConeClosureForLeftSide(leftSide); } } else { Z = SweepDirection * leftIntersectionEvent.Site; } }
void CreateConeClosureEvent(BrokenConeSide brokenConeSide, ConeSide otherSide) { Point x; bool r = Point.RayIntersectsRayInteriors(brokenConeSide.start, brokenConeSide.Direction, otherSide.Start, otherSide.Direction, out x); Debug.Assert(r); EnqueueEvent(new ConeClosureEvent(x, brokenConeSide.Cone)); }
void TryIntersectionOfConeRightSideAndObstacleConeSide(ConeRightSide coneRightSide, BrokenConeSide seg) { Point x; if (Point.IntervalIntersectsRay(seg.Start, seg.End, coneRightSide.Start, coneRightSide.Direction, out x)) { EnqueueEvent(CreateRightIntersectionEvent(coneRightSide, x, seg.EndVertex)); //Show(CurveFactory.CreateDiamond(3, 3, x)); } }
void TryCreateConeClosureForRightSide(BrokenConeSide rightSide) { var coneLeftSide = rightSide.Cone.LeftSide as ConeLeftSide; if (coneLeftSide != null) { if ( Point.GetTriangleOrientation(coneLeftSide.Start, coneLeftSide.Start + coneLeftSide.Direction, rightSide.EndVertex.Point) == TriangleOrientation.Counterclockwise) { CreateConeClosureEvent(rightSide, coneLeftSide); } } }
int CompareBrokenSides(BrokenConeSide aObst, BrokenConeSide bObst) { if (aObst.EndVertex == bObst.EndVertex) { return(CompareNotIntersectingSegs(aObst.ConeSide, bObst.ConeSide)); } if (Point.GetTriangleOrientation(x, bObst.Start, bObst.EndVertex.Point) == TriangleOrientation.Counterclockwise) { return(-1); } return(1); }
int CompareConeSideAndObstacleSide(ConeSide coneSide, BrokenConeSide brokenConeSide) { var orientation = Point.GetTriangleOrientation(x, brokenConeSide.Start, brokenConeSide.End); if (orientation == TriangleOrientation.Counterclockwise) { return(-1); } if (orientation == TriangleOrientation.Clockwise) { return(1); } //we have the case where x belongs to the cone side // lineSweeper.Show(CurveFactory.CreateDiamond(5,5, brokenConeSide.EndVertex.Point)); return(coneSide is ConeLeftSide ? 1 : -1); }
/// <summary> /// /// </summary> /// <param name="rightSide"></param> /// <param name="rbNode">represents a node of the right cone side</param> void FixConeRightSideIntersections(BrokenConeSide rightSide, RBNode<ConeSide> rbNode) { //the first intersection can happen only with predecessors of rightSide Debug.Assert(rbNode != null); do { //this loop usually works only once rbNode = rightConeSides.Previous(rbNode); } while (rbNode != null && Point.PointToTheLeftOfLineOrOnLine(rightSide.Start, rbNode.Item.Start, rbNode.Item.Start + rbNode.Item.Direction)); if (rbNode != null) { Point intersection; var seg = rbNode.Item as ConeRightSide; if (seg != null && Point.IntervalIntersectsRay(rightSide.Start, rightSide.End, seg.Start, seg.Direction, out intersection)) { EnqueueEvent(CreateRightIntersectionEvent(seg, intersection, rightSide.EndVertex)); // Show(CurveFactory.CreateDiamond(3, 3, intersection)); } } }
void TryIntersectionOfConeLeftSideAndObstacleConeSide(ConeLeftSide coneLeftSide, BrokenConeSide seg) { Point x; if (Point.IntervalIntersectsRay(seg.Start, seg.End, coneLeftSide.Start, coneLeftSide.Direction, out x)) { EnqueueEvent(new LeftIntersectionEvent(coneLeftSide, x, seg.EndVertex)); //Show(CurveFactory.CreateDiamond(3, 3, x)); } }
void CaseToTheLeftOfLineOrOnLineConeRp(VertexEvent rightVertexEvent, PolylinePoint nextVertex) { EnqueueEvent(new RightVertexEvent(nextVertex)); //the obstacle side is inside of the cone //we need to create an obstacle left side segment instead of the left cone side var cone = new Cone(rightVertexEvent.Vertex.Point, this); var obstacleSideSeg = new BrokenConeSide(cone.Apex, nextVertex, new ConeLeftSide(cone)); cone.LeftSide = obstacleSideSeg; cone.RightSide = new ConeRightSide(cone); var rnode = InsertToTree(rightConeSides, cone.RightSide); LookForIntersectionWithConeRightSide(rnode); var lnode = InsertToTree(leftConeSides, cone.LeftSide); FixConeLeftSideIntersections(obstacleSideSeg, lnode); if ((nextVertex.Point - rightVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon) InsertRightSide(new RightObstacleSide(rightVertexEvent.Vertex)); }
void CloseConesAddConeAtLeftVertex(VertexEvent leftVertexEvent, PolylinePoint nextVertex) { //close segments first Point prevSite = leftVertexEvent.Vertex.PrevOnPolyline.Point; double prevZ = prevSite * SweepDirection; if (ApproximateComparer.Close(prevZ, Z) && (prevSite - leftVertexEvent.Site) * DirectionPerp > 0) { //Show( // new Ellipse(1, 1, prevSite), // CurveFactory.CreateBox(2, 2, leftVertexEvent.Vertex.Point)); RemoveConesClosedBySegment(leftVertexEvent.Vertex.Point, prevSite); } var site = leftVertexEvent.Site; var coneLp = site + ConeLeftSideDirection; var coneRp = site + ConeRightSideDirection; var nextSite = nextVertex.Point; // SugiyamaLayoutSettings.Show(new LineSegment(site, coneLP), new LineSegment(site, coneRP), new LineSegment(site, nextSite)); if ((site - prevSite) * SweepDirection > ApproximateComparer.DistanceEpsilon) RemoveLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex.PrevOnPolyline)); var nextDelZ = GetZ(nextSite) - Z; if(nextDelZ<-ApproximateComparer.DistanceEpsilon) RemoveRightSide(new RightObstacleSide(nextVertex)); if (nextDelZ < -ApproximateComparer.DistanceEpsilon || ApproximateComparer.Close(nextDelZ, 0) && (nextSite - leftVertexEvent.Site) * DirectionPerp > 0) { //if (angle > Math.PI / 2) CreateConeOnVertex(leftVertexEvent); //it is the last left vertex on this obstacle } else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneRp)) { //if (angle >= coneAngle / 2) { CreateConeOnVertex(leftVertexEvent); EnqueueEvent(new LeftVertexEvent(nextVertex)); //we schedule LeftVertexEvent for a vertex with horizontal segment to the left on the top of the obstace } else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneLp)) { //if (angle >= -coneAngle / 2) { //we cannot completely obscure the cone here EnqueueEvent(new LeftVertexEvent(nextVertex)); //the obstacle side is inside of the cone //we need to create an obstacle right side segment instead of the cone side var cone = new Cone(leftVertexEvent.Vertex.Point, this); var rightSide = new BrokenConeSide(leftVertexEvent.Vertex.Point, nextVertex, new ConeRightSide(cone)); cone.RightSide = rightSide; cone.LeftSide = new ConeLeftSide(cone); LookForIntersectionWithConeLeftSide(InsertToTree(leftConeSides, cone.LeftSide)); var rbNode = InsertToTree(rightConeSides, rightSide); FixConeRightSideIntersections(rightSide, rbNode); if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon) InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex)); } else { EnqueueEvent(new LeftVertexEvent(nextVertex)); if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon) { //if( angle >- Pi/2 // Debug.Assert(angle > -Math.PI / 2); LookForIntersectionOfObstacleSideAndRightConeSide(leftVertexEvent.Site, nextVertex); InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex)); } } }
void TryCreateConeClosureForRightSide(BrokenConeSide rightSide) { var coneLeftSide = rightSide.Cone.LeftSide as ConeLeftSide; if (coneLeftSide != null) if ( Point.GetTriangleOrientation(coneLeftSide.Start, coneLeftSide.Start + coneLeftSide.Direction, rightSide.EndVertex.Point) == TriangleOrientation.Counterclockwise) CreateConeClosureEvent(rightSide, coneLeftSide); }
void ProcessRightIntersectionEvent(RightIntersectionEvent rightIntersectionEvent) { //restore Z for the time being // Z = PreviousZ; if (rightIntersectionEvent.coneRightSide.Removed == false) { //it can happen that the cone side participating in the intersection is gone; //obstracted by another obstacle or because of a vertex found inside of the cone //PrintOutRightSegTree(); RemoveSegFromRightTree(rightIntersectionEvent.coneRightSide); Z = SweepDirection * rightIntersectionEvent.Site; var rightSide = new BrokenConeSide( rightIntersectionEvent.Site, rightIntersectionEvent.EndVertex, rightIntersectionEvent.coneRightSide); InsertToTree(rightConeSides, rightSide); rightIntersectionEvent.coneRightSide.Cone.RightSide = rightSide; LookForIntersectionOfObstacleSideAndRightConeSide(rightIntersectionEvent.Site, rightIntersectionEvent.EndVertex); TryCreateConeClosureForRightSide(rightSide); } else Z = SweepDirection * rightIntersectionEvent.Site; }
void CreateConeClosureEvent(BrokenConeSide brokenConeSide, ConeSide otherSide) { Point x; #if DEBUG && TEST_MSAGL var r = #endif Point.RayIntersectsRayInteriors(brokenConeSide.start, brokenConeSide.Direction, otherSide.Start, otherSide.Direction, out x); #if DEBUG && TEST_MSAGL if (!r) LayoutAlgorithmSettings.ShowDebugCurves( new DebugCurve(100, 0.1, "red",new LineSegment(brokenConeSide.Start, brokenConeSide.start + brokenConeSide.Direction)), new DebugCurve(100,0.1, "black", new Ellipse(0.1,0.1, brokenConeSide.Start)), new DebugCurve(100, 0.1, "blue",new LineSegment(otherSide.Start, otherSide.Start + otherSide.Direction))); Debug.Assert(r); #endif EnqueueEvent(new ConeClosureEvent(x, brokenConeSide.Cone)); }
void ProcessLeftIntersectionEvent(LeftIntersectionEvent leftIntersectionEvent) { if (leftIntersectionEvent.coneLeftSide.Removed == false) { if (Math.Abs((leftIntersectionEvent.EndVertex.Point - leftIntersectionEvent.Site) * SweepDirection) < ApproximateComparer.DistanceEpsilon) { //the cone is totally covered by a horizontal segment RemoveCone(leftIntersectionEvent.coneLeftSide.Cone); } else { RemoveSegFromLeftTree(leftIntersectionEvent.coneLeftSide); Z = SweepDirection * leftIntersectionEvent.Site; //it is safe now to restore the order var leftSide = new BrokenConeSide( leftIntersectionEvent.Site, leftIntersectionEvent.EndVertex, leftIntersectionEvent.coneLeftSide); InsertToTree(leftConeSides, leftSide); leftIntersectionEvent.coneLeftSide.Cone.LeftSide = leftSide; LookForIntersectionOfObstacleSideAndLeftConeSide(leftIntersectionEvent.Site, leftIntersectionEvent.EndVertex); TryCreateConeClosureForLeftSide(leftSide); } } else Z = SweepDirection * leftIntersectionEvent.Site; }