public Segment(VoronoiEdge edge, Rectangle bounds) { _bounds = bounds; Left = edge.LeftData.ToPointF(); Right = edge.RightData.ToPointF(); var x1 = (int)edge.VVertexA[0]; var y1 = (int)edge.VVertexA[1]; var x2 = (int)edge.VVertexB[0]; var y2 = (int)edge.VVertexB[1]; if (x1 > x2 || (x1 == x2 && y1 > y2)) { Start = edge.VVertexB.ToPointF(); End = edge.VVertexA.ToPointF(); } else { Start = edge.VVertexA.ToPointF(); End = edge.VVertexB.ToPointF(); } }
protected void RemoveConnectionsParticular(VoronoiEdge edge, bool point1) { if (point1) { foreach (VoronoiEdge connection in edge.point1connections) { if (connection.point1 == edge.point1) { connection.point1connections.Remove(edge); } else { connection.point2connections.Remove(edge); } } } else { foreach (VoronoiEdge connection in edge.point2connections) { if (connection.point1 == edge.point2) { connection.point1connections.Remove(edge); } else { connection.point2connections.Remove(edge); } } } }
public Bitmap GetMapTemperature(int weight, int height) { Bitmap bmp = new Bitmap(weight, height); Graphics g = Graphics.FromImage(bmp); foreach (TemperatureLocation t in temperature) { Vector v = new Vector(t.X, t.Y); foreach (object obj in graph.Edges) { VoronoiEdge e = (VoronoiEdge)obj; if (((e.LeftData[0] == v[0]) & (e.LeftData[1] == v[1])) | ((e.RightData[0] == v[0]) & (e.RightData[1] == v[1]))) { SolidBrush brush = new SolidBrush(GetColorOfPoint(v[0], v[1])); try { g.FillPolygon(brush, new Point[3] { new Point((int)v[0], (int)v[1]), new Point((int)e.VVertexA[0], (int)e.VVertexA[1]), new Point((int)e.VVertexB[0], (int)e.VVertexB[1]) }); } catch { } } //g.DrawLine(Pens.Black, (int)e.VVertexA[0], (int)e.VVertexA[1], (int)e.VVertexB[0], (int)e.VVertexB[1]); } } return(Smooth(bmp)); }
protected void ChangeConnections(VoronoiEdge edgeIndex, VoronoiEdge indexToConnect, bool point1) { if (point1) { foreach (VoronoiEdge connection in edgeIndex.point1connections) { if (connection.point1 == edgeIndex.point1) { connection.point1connections.Remove(edgeIndex); connection.point1connections.Add(indexToConnect); } else { connection.point2connections.Remove(edgeIndex); connection.point2connections.Add(indexToConnect); } } } else { foreach (VoronoiEdge connection in edgeIndex.point2connections) { if (connection.point1 == edgeIndex.point2) { connection.point1connections.Remove(edgeIndex); connection.point1connections.Add(indexToConnect); } else { connection.point2connections.Remove(edgeIndex); connection.point2connections.Add(indexToConnect); } } } }
public static Edge Pack_into_Edge(VoronoiEdge VE) { int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; if (VE.IsInfinite) { x1 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y1 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); x2 = (int)(-1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(-1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else if (VE.IsPartlyInfinite) { x1 = (int)VE.FixedPoint[0]; y1 = (int)VE.FixedPoint[1]; x2 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else { x1 = (int)VE.VVertexA[0]; y1 = (int)VE.VVertexA[1]; x2 = (int)VE.VVertexB[0]; y2 = (int)VE.VVertexB[1]; } Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); Edge e = new Edge(p1, p2); return(e); }
public void CompleteEdge(VoronoiNode node) { if (!node.hasChildren()) { return; } VoronoiEdgeNode edge = (VoronoiEdgeNode)node; float height = Camera.main.orthographicSize; float width = height * Camera.main.aspect; float max; if (edge.mDirection.x > 0.0f) { max = Mathf.Max(width, edge.mStartVertex.x); } else { max = Mathf.Min(-width, edge.mStartVertex.x); } Vector2 endVertex = new Vector2(max, max * edge.slope + edge.yIntercept); edge.mEndVertex = endVertex; VoronoiEdge newRenderEdge = Instantiate(voronoiEdgePrefab, new Vector2(), Quaternion.identity).GetComponent <VoronoiEdge>(); newRenderEdge.SetPosition(edge.mStartVertex, edge.mEndVertex); edges.Add(newRenderEdge); CompleteEdge(node.mLeft); CompleteEdge(node.mRight); }
private void DrawEdge(float[,] cutPattern, VoronoiEdge voronoiEdge) { if (voronoiEdge.IsPartlyInfinite || voronoiEdge.IsInfinite) { return; } var dirvec = voronoiEdge.V2 - voronoiEdge.V1; var myDir = new Vector2((float)dirvec[0], (float)dirvec[1]); //Debug.Log("Left: " + voronoiEdge.V2); //Debug.Log("Right: " + voronoiEdge.V1); while (myDir.magnitude != 0) { if ((int)(voronoiEdge.V1[0] + myDir.x) < 0 || (int)(voronoiEdge.V1[1] + myDir.y) < 0 || (int)(voronoiEdge.V1[0] + myDir.x) >= cutPattern.GetLength(0) || (int)(voronoiEdge.V1[1] + myDir.y) >= cutPattern.GetLength(1)) { myDir *= 0; continue; } cutPattern[(int)(voronoiEdge.V1[0] + myDir.x), (int)(voronoiEdge.V1[1] + myDir.y)] = 0.5f; var scale = ((myDir.magnitude - 0.5f) / myDir.magnitude); myDir *= scale < 0 ? 0 : scale; } }
protected int CrossBounds(VoronoiEdge edge, ref Vector2 intersectionUp, ref Vector2 intersectionRight, ref Vector2 intersectionDown, ref Vector2 intersectionLeft) { bool a = UniversalIntersect(edge.point1, edge.point2, EdgeType(edge), upperLeftCorner, upperRightCorner, 3, ref intersectionUp); bool b = UniversalIntersect(edge.point1, edge.point2, EdgeType(edge), upperRightCorner, lowerRightCorner, 3, ref intersectionRight); bool c = UniversalIntersect(edge.point1, edge.point2, EdgeType(edge), lowerRightCorner, lowerLeftCorner, 3, ref intersectionDown); bool d = UniversalIntersect(edge.point1, edge.point2, EdgeType(edge), lowerLeftCorner, upperLeftCorner, 3, ref intersectionLeft); int result = 0; if (a) { result += 1; } if (b) { result += 2; } if (c) { result += 4; } if (d) { result += 8; } return(result); }
//Try to add a voronoi edge. Not all edges have a neighboring triangle, and if it hasnt we cant add a voronoi edge private static void TryAddVoronoiEdgeFromTriangleEdge(HalfEdge e, Vector3 voronoiVertex, List <VoronoiEdge> allEdges) { //Ignore if this edge has no neighboring triangle if (e.oppositeEdge == null) { return; } //Calculate the circumcenter of the neighbor HalfEdge eNeighbor = e.oppositeEdge; Vector3 v1 = eNeighbor.v.position; Vector3 v2 = eNeighbor.nextEdge.v.position; Vector3 v3 = eNeighbor.nextEdge.nextEdge.v.position; //The .XZ() is an extension method that removes the y value of a vector3 so it becomes a vector2 Vector2 center2D = Geometry.CalculateCircleCenter(v1.XZ(), v2.XZ(), v3.XZ()); Vector3 voronoiVertexNeighbor = new Vector3(center2D.x, 0f, center2D.y); //Create a new voronoi edge between the voronoi vertices VoronoiEdge edge = new VoronoiEdge(voronoiVertex, voronoiVertexNeighbor, e.prevEdge.v.position); allEdges.Add(edge); }
protected void RemoveConnections(VoronoiEdge edge) { foreach (VoronoiEdge connection in edge.point1connections) { if (connection.point1 == edge.point1) { connection.point1connections.Remove(edge); } else { connection.point2connections.Remove(edge); } } foreach (VoronoiEdge connection in edge.point2connections) { if (connection.point1 == edge.point2) { connection.point1connections.Remove(edge); } else { connection.point2connections.Remove(edge); } } }
private void DrawVoronoiEdge(VoronoiEdge VE) { int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; if (VE.IsInfinite) { x1 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y1 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); x2 = (int)(-1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(-1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else if (VE.IsPartlyInfinite) { x1 = (int)VE.FixedPoint[0]; y1 = (int)VE.FixedPoint[1]; x2 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else { x1 = (int)VE.VVertexA[0]; y1 = (int)VE.VVertexA[1]; x2 = (int)VE.VVertexB[0]; y2 = (int)VE.VVertexB[1]; } GL.LineWidth(1); GL.Begin(BeginMode.Lines); GL.Color3(Color.Black); GL.Vertex2(x1, y1); GL.Vertex2(x2, y2); GL.End(); }
public static VNode ProcessCircleEvent(VCircleEvent e, VNode root, VoronoiGraph vg, out VDataNode[] circleCheckList) { VEdgeNode eo; var b = e.NodeN; var a = LeftDataNode(b); var c = RightDataNode(b); if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { circleCheckList = new VDataNode[] { }; return(root); // Abbruch da sich der Graph verändert hat } var eu = (VEdgeNode)b.Parent; circleCheckList = new[] { a, c }; //1. Create the new Vertex var vNew = new Vector2((float)e.CenterX, (float)e.CenterY); vg.AddVertex(vNew); //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex if (eu.Left == b) // c is sibling { eo = EdgeToRightDataNode(a); // replace eu by eu's Right eu.Parent.Replace(eu, eu.Right); } else // a is sibling { eo = EdgeToRightDataNode(b); // replace eu by eu's Left eu.Parent.Replace(eu, eu.Left); } eu.Edge.AddVertex(vNew); eo.Edge.AddVertex(vNew); //2. Replace eo by new Edge var ve = new VoronoiEdge { LeftData = a.DataPoint, RightData = c.DataPoint }; ve.AddVertex(vNew); vg.AddEdge(ve); var ven = new VEdgeNode(ve, false) { Left = eo.Left, Right = eo.Right }; if (eo.Parent == null) { return(ven); } eo.Parent.Replace(eo, ven); return(root); }
public IslandTileEdge(VoronoiEdge e) { edge = e; // Corner Index are assumed to be populated from IslandTile cornerA = IslandTileCorner.Index[e.VVertexA]; cornerB = IslandTileCorner.Index[e.VVertexB]; }
private static VNode ProcessDataEvent(VDataEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { if (Root == null) { Root = new VDataNode(e.DataPoint); CircleCheckList = new VDataNode[] { (VDataNode)Root }; return(Root); } //Знаходимо вузол для заміщення VNode C = VNode.FindDataNode(Root, ys, e.DataPoint[0]); //Створюємо піддерево з одним ребром, але двома VEdgeNodes VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = ((VDataNode)C).DataPoint; VE.RightData = e.DataPoint; VE.VVertexA = Fortune.VVUnkown; VE.VVertexB = Fortune.VVUnkown; VG.Edges.Add(VE); VNode SubRoot; if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10) { if (VE.LeftData[0] < VE.RightData[0]) { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VDataNode(VE.RightData); } else { SubRoot = new VEdgeNode(VE, true); SubRoot.Left = new VDataNode(VE.RightData); SubRoot.Right = new VDataNode(VE.LeftData); } CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right }; } else { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VEdgeNode(VE, true); SubRoot.Right.Left = new VDataNode(VE.RightData); SubRoot.Right.Right = new VDataNode(VE.LeftData); CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right.Left, (VDataNode)SubRoot.Right.Right }; } //"Застосовуємо" піддерево if (C.Parent == null) { return(SubRoot); } C.Parent.Replace(C, SubRoot); return(Root); }
public static VNode ProcessDataEvent(VDataEvent vertexevent, VNode root, VoronoiGraph veronoigraphbox, double vertexeventycoord, out VDataNode[] circleCheckList) { if (root == null) { root = new VDataNode(vertexevent.DataPoint); circleCheckList = new VDataNode[] { (VDataNode)root }; return(root); } //1. Find the node to be replaced VNode C = NodeHandler.FindDataNode(root, vertexeventycoord, vertexevent.DataPoint[0]); //2. Create the subtree (ONE Edge, but two VEdgeNodes) VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = ((VDataNode)C).DataPoint; VE.RightData = vertexevent.DataPoint; VE.VVertexA = Constants.VVUnkown; VE.VVertexB = Constants.VVUnkown; veronoigraphbox.Edges.Add(VE); VNode SubRoot; if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10) { if (VE.LeftData[0] < VE.RightData[0]) { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VDataNode(VE.RightData); } else { SubRoot = new VEdgeNode(VE, true); SubRoot.Left = new VDataNode(VE.RightData); SubRoot.Right = new VDataNode(VE.LeftData); } circleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right }; } else { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VEdgeNode(VE, true); SubRoot.Right.Left = new VDataNode(VE.RightData); SubRoot.Right.Right = new VDataNode(VE.LeftData); circleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right.Left, (VDataNode)SubRoot.Right.Right }; } //3. Apply subtree if (C.Parent == null) { return(SubRoot); } C.Parent.Replace(C, SubRoot); return(root); }
private static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { VDataNode a, b, c; VEdgeNode e1, e2; b = e.NodeN; a = VNode.LeftDataNode(b); c = VNode.RightDataNode(b); if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { CircleCheckList = new VDataNode[] { }; return(Root); // повертаємось, бо графік змінився } e1 = (VEdgeNode)b.Parent; CircleCheckList = new VDataNode[] { a, c }; //Створюємо нову вершину Vector VNew = new Vector(e.Center[0], e.Center[1]); VG.Vertizes.Add(VNew); //2. виясняємо, чи а або с знаходяться у віддаленій частині дерева (інший - брат b), і призначаємо нову вершину if (e1.Left == b) // c - брат { e2 = VNode.EdgeToRightDataNode(a); // замінюємо e1 правим нащадком e1.Parent.Replace(e1, e1.Right); } else // a - брат { e2 = VNode.EdgeToRightDataNode(b); // замінюємо e1 лівим нащадком e1.Parent.Replace(e1, e1.Left); } e1.Edge.AddVertex(VNew); e2.Edge.AddVertex(VNew); //Замінюємо e2 новим ребром VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = a.DataPoint; VE.RightData = c.DataPoint; VE.AddVertex(VNew); VG.Edges.Add(VE); VEdgeNode VEN = new VEdgeNode(VE, false); VEN.Left = e2.Left; VEN.Right = e2.Right; if (e2.Parent == null) { return(VEN); } e2.Parent.Replace(e2, VEN); return(Root); }
private int MainEdgeType(VoronoiEdge prev) { if (prev != null) { return(1); } else { return(0); } }
//Find the position in the list of all cells that includes this site //Returns -1 if no cell is found private static int TryFindCellPos(VoronoiEdge e, List <VoronoiCell> voronoiCells) { for (int i = 0; i < voronoiCells.Count; i++) { if (e.sitePos == voronoiCells[i].sitePos) { return(i); } } return(-1); }
public static void TestRotationVelocity() { double rotation = VoronoiEdge.RotationVelocity( new double[] { 1, 0 }, new double[] { 0, 1 }, new double[] { -1, 0 }, new double[] { 0, -1 }, new double[] { 0, -1 }); double expectedRotation = 1; Assert.IsTrue(Math.Abs(rotation - expectedRotation) < 1e-12, "Speed of rotation is not correct."); }
public bool isPoint1; // Является ли точка первой в ребре или нет public BoundIntersection(Vector2 newPoint, VoronoiEdge newEdge) { point = newPoint; edge = newEdge; if (point == edge.point1) { isPoint1 = true; } else { isPoint1 = false; } }
private void AddCorners(VoronoiEdge e) { IslandTileCorner cA = AddCorner(e.VVertexA); IslandTileCorner cB = AddCorner(e.VVertexB); cA.protrudes.Add(e); cA.adjacent.Add(cB); cA.touches.Add(this); cB.protrudes.Add(e); cB.adjacent.Add(cA); cB.touches.Add(this); }
public override bool Equals(object obj) { VoronoiEdge <TVertex, TCell> voronoiEdge = obj as VoronoiEdge <TVertex, TCell>; if (voronoiEdge == null) { return(false); } if (object.ReferenceEquals(this, voronoiEdge)) { return(true); } return((Source == voronoiEdge.Source && Target == voronoiEdge.Target) || (Source == voronoiEdge.Target && Target == voronoiEdge.Source)); }
protected int EdgeType(VoronoiEdge edge) { int result = 0; if (edge.point1connections.Count > 0) { result += 1; } if (edge.point2connections.Count > 0) { result += 2; } return(result); }
private int NumConnectedEdges(VoronoiEdge edge, HashSet <IslandTileEdge> es) { int numConnectedEdges = 0; foreach (IslandTileEdge e in es) { if (e.edge.VVertexA == edge.VVertexA || e.edge.VVertexA == edge.VVertexB || e.edge.VVertexB == edge.VVertexA || e.edge.VVertexB == edge.VVertexB) { numConnectedEdges++; } } return(numConnectedEdges); }
public static Edge MapVoronoiEdgeToEdge(this VoronoiEdge Source, double ActualHeigth, bool Voronoi = true, bool scaled = false) { Edge Result = new Edge(); if (Voronoi) { Result.A = Source.VVertexA.MapVectorToPoint(ActualHeigth, scaled); Result.B = Source.VVertexB.MapVectorToPoint(ActualHeigth, scaled); } else { Result.A = Source.LeftData.MapVectorToPoint(ActualHeigth, scaled); Result.B = Source.RightData.MapVectorToPoint(ActualHeigth, scaled); } return(Result); }
protected void ConnectEdges(VoronoiEdge edgeIndex, VoronoiEdge indexToConnect) { foreach (VoronoiEdge connection in edgeIndex.point2connections) { if (connection.point1 == edgeIndex.point2) { connection.point1connections.Add(indexToConnect); } else { connection.point2connections.Add(indexToConnect); } indexToConnect.point1connections.Add(connection); } edgeIndex.point2connections.Add(indexToConnect); indexToConnect.point1connections.Add(edgeIndex); }
public void OrderPoints(VoronoiEdge edge, out PointF pointA, out PointF pointB) { var x1 = (int)edge.VVertexA[0]; var y1 = (int)edge.VVertexA[1]; var x2 = (int)edge.VVertexB[0]; var y2 = (int)edge.VVertexB[1]; if (x1 > x2 || (x1 == x2 && y1 > y2)) { pointA = edge.VVertexB.ToPointF(); pointB = edge.VVertexA.ToPointF(); } else { pointA = edge.VVertexA.ToPointF(); pointB = edge.VVertexB.ToPointF(); } }
private Point[] GenerateJaggedSegment(VoronoiEdge edge) { var t = Interpolate(edge.VVertexA, edge.LeftData, NoisyLineTradeoff); var q = Interpolate(edge.VVertexA, edge.RightData, NoisyLineTradeoff); var r = Interpolate(edge.VVertexB, edge.LeftData, NoisyLineTradeoff); var s = Interpolate(edge.VVertexB, edge.RightData, NoisyLineTradeoff); var midpoint = Interpolate(edge.VVertexA, edge.VVertexB, 0.5); var points = new List <Point>(); var segment1 = BuildNoisyLineSegments(edge.VVertexA, t, midpoint, q, MinimumJaggedLength); points.AddRange(segment1.Select(v => v.ToPoint())); var segment2 = BuildNoisyLineSegments(edge.VVertexB, s, midpoint, r, MinimumJaggedLength); points.AddRange(segment2.Select(v => v.ToPoint()).Reverse()); return(points.ToArray()); }
protected void WatchEdge(VoronoiEdge watchIndex, ref List <VoronoiEdge> list) { foreach (VoronoiEdge j in watchIndex.point1connections) { if (!list.Contains(j)) { list.Add(j); WatchEdge(j, ref list); } } foreach (VoronoiEdge j in watchIndex.point2connections) { if (!list.Contains(j)) { list.Add(j); WatchEdge(j, ref list); } } }
private void AddEdge(VoronoiEdge e) { bool isInf = (e.VVertexA == Fortune.VVInfinite) || (e.VVertexB == Fortune.VVInfinite); if (isInf) { return; } AddCorners(e); edges.Add(new IslandTileEdge(e)); if (e.LeftData == center) { neighbors.Add(e.RightData); } else { neighbors.Add(e.LeftData); } }
public static Edge Pack_into_Edge(VoronoiEdge VE) { int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; if (VE.IsInfinite) { x1 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y1 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); x2 = (int)(-1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(-1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else if (VE.IsPartlyInfinite) { x1 = (int)VE.FixedPoint[0]; y1 = (int)VE.FixedPoint[1]; x2 = (int)(1000 * VE.DirectionVector[0] + VE.FixedPoint[0]); y2 = (int)(1000 * VE.DirectionVector[1] + VE.FixedPoint[1]); } else { x1 = (int)VE.VVertexA[0]; y1 = (int)VE.VVertexA[1]; x2 = (int)VE.VVertexB[0]; y2 = (int)VE.VVertexB[1]; } Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); Edge e = new Edge(p1, p2); return e; }
private static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { VDataNode a, b, c; VEdgeNode e1, e2; b = e.NodeN; a = VNode.LeftDataNode(b); c = VNode.RightDataNode(b); if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { CircleCheckList = new VDataNode[] { }; return Root; // повертаємось, бо графік змінився } e1 = (VEdgeNode)b.Parent; CircleCheckList = new VDataNode[] { a, c }; //Створюємо нову вершину Vector VNew = new Vector(e.Center[0], e.Center[1]); VG.Vertizes.Add(VNew); //2. виясняємо, чи а або с знаходяться у віддаленій частині дерева (інший - брат b), і призначаємо нову вершину if (e1.Left == b) // c - брат { e2 = VNode.EdgeToRightDataNode(a); // замінюємо e1 правим нащадком e1.Parent.Replace(e1, e1.Right); } else // a - брат { e2 = VNode.EdgeToRightDataNode(b); // замінюємо e1 лівим нащадком e1.Parent.Replace(e1, e1.Left); } e1.Edge.AddVertex(VNew); e2.Edge.AddVertex(VNew); //Замінюємо e2 новим ребром VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = a.DataPoint; VE.RightData = c.DataPoint; VE.AddVertex(VNew); VG.Edges.Add(VE); VEdgeNode VEN = new VEdgeNode(VE, false); VEN.Left = e2.Left; VEN.Right = e2.Right; if (e2.Parent == null) return VEN; e2.Parent.Replace(e2, VEN); return Root; }
private static VNode ProcessDataEvent(VDataEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { if (Root == null) { Root = new VDataNode(e.DataPoint); CircleCheckList = new VDataNode[] { (VDataNode)Root }; return Root; } //Знаходимо вузол для заміщення VNode C = VNode.FindDataNode(Root, ys, e.DataPoint[0]); //Створюємо піддерево з одним ребром, але двома VEdgeNodes VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = ((VDataNode)C).DataPoint; VE.RightData = e.DataPoint; VE.VVertexA = Fortune.VVUnkown; VE.VVertexB = Fortune.VVUnkown; VG.Edges.Add(VE); VNode SubRoot; if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10) { if (VE.LeftData[0] < VE.RightData[0]) { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VDataNode(VE.RightData); } else { SubRoot = new VEdgeNode(VE, true); SubRoot.Left = new VDataNode(VE.RightData); SubRoot.Right = new VDataNode(VE.LeftData); } CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right }; } else { SubRoot = new VEdgeNode(VE, false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VEdgeNode(VE, true); SubRoot.Right.Left = new VDataNode(VE.RightData); SubRoot.Right.Right = new VDataNode(VE.LeftData); CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right.Left, (VDataNode)SubRoot.Right.Right }; } //"Застосовуємо" піддерево if (C.Parent == null) return SubRoot; C.Parent.Replace(C, SubRoot); return Root; }