private static List<Intersection> CutByLineVertical(Vertex s1, Vertex s2, LinkedList<VertexBase> linkC) { var crossXs = new List<Intersection>(); var x = s1.X; List<VertexBase> shearedPolyC = linkC.ToList(); var minY = s1.Y > s2.Y ? s2.Y : s1.Y; var maxY = s1.Y > s2.Y ? s1.Y : s2.Y; int i = -1; bool backToHead = false; for (var vertex = linkC.First; //这样回到头部的线也可以正常被切到 vertex != null && ((vertex.Value is Vertex && vertex.Next != null) || ((vertex.Value is Intersection) && ((Intersection)vertex.Value).NextC != null) || (vertex.Value is Vertex && vertex.Next == null && !backToHead) || (vertex.Value is Intersection && ((Intersection)vertex.Value).NextC == null && !backToHead)); vertex = vertex.Next) { i++; var c1 = shearedPolyC[i % shearedPolyC.Count]; var c2 = shearedPolyC[(i + 1)%shearedPolyC.Count]; // 重合 if (c1.X == c2.X && c1.X == x) continue; //不相交 if (c1.X > x && c2.X > x) continue; if (c1.X < x && c2.X < x) continue; var y = LineCrossV(x, c1, c2); var inters = new Intersection(x, y); VertexBase next = null; if ((y > minY && y < maxY) || (c2.X == x && y == minY) || (c2.X == x && y == maxY) || (y == minY && c1.X != x && c2.X != x) || (y == maxY && c1.X != x && c2.X != x)) { inters.Name = "I" + Counter.Default.Val++; if (vertex.Next == null) { backToHead = true; next = linkC.First.Value; } else { next = vertex.Next.Value; } WindowLog.Default.Log("切割C的边{0}{1}得到交点{2}", vertex.Value.Name, next.Name, inters.Name); inters.NextC = next; if (vertex.Value is Vertex) (vertex.Value as Vertex).Next = inters; else if (vertex.Value is Intersection) (vertex.Value as Intersection).NextC = inters; linkC.AddAfter(vertex, inters); vertex = vertex.Next; crossXs.Add(inters); } if (backToHead) break; #region log var cLinkSb = new StringBuilder(); var v = linkC.First.Value; while (v != null) { cLinkSb.Append(v.Name); if (v is Intersection) { var curr = v as Intersection; next = curr.NextC; } else if (v is Vertex) { var curr = v as Vertex; next = curr.Next; } if (next.Equals(linkC.First.Value)) { break; } v = next; cLinkSb.Append("->"); } WindowLog.Default.Log("C链表:" + cLinkSb); #endregion } return crossXs; }
private void MoveOver(object sender, MouseEventArgs e) { _cross.Visible = false; var point = e.GetPosition(Canvas); PointVec.Text = "坐标位置:" + point.X + "," + point.Y; var newVector = new Vertex(point.X, point.Y); if (Keyboard.IsKeyDown(Key.LeftShift) && (_drawingPolygonC || _drawingPolygonS)) { VertexBase pointPre = null; if (_drawingPolygonS) pointPre = _polyS.PointList[_polygonSVertexNum - 2]; else if (_drawingPolygonC) pointPre = _polyC.PointList[_polygonCVertexNum - 2]; var dx = pointPre.X - point.X; double tan = 0; if (dx != 0) { var dy = pointPre.Y - point.Y; tan = Math.Abs(dy / dx); } else { tan = double.MaxValue; } if (tan <= 1) newVector = new Vertex(point.X, (double)pointPre.Y); else if (tan > 1) { newVector = new Vertex((double)pointPre.X, point.Y); } } //抓去最近点 Point nearestPoint = new Point(); bool hasNearestSite = false; if (_drawingPolygonS) hasNearestSite = IsCloseToPolygon(point, _polyC, ref nearestPoint); else if (_drawingPolygonC) hasNearestSite = IsCloseToPolygon(point, _polyS, ref nearestPoint); if (hasNearestSite) { _cross.Center = nearestPoint; _cross.Visible = true; var screenPoint = Canvas.PointToScreen(nearestPoint); SetCursorPos((int)screenPoint.X,(int)screenPoint.Y); } if (_drawingPolygonS && _polygonSVertexNum > 0) { _polyS.PointList[_polygonSVertexNum - 1].SetXY(newVector.X, newVector.Y); _polyS.Render(Canvas); } if (_drawingPolygonC && _polygonCVertexNum > 0) { _polyC.PointList[_polygonCVertexNum - 1].SetXY(newVector.X, newVector.Y); _polyC.Render(Canvas); } }
/// <summary> /// 用实体多边形S的边切割切割多边形C,并插入交点到C中 /// </summary> /// <param name="s1"></param> /// <param name="s2"></param> /// <param name="linkC"></param> /// <returns></returns> private static List<Intersection> CutByLine(Vertex s1, Vertex s2, LinkedList<VertexBase> linkC) { if (s1.X == s2.X) return CutByLineVertical(s1, s2, linkC); var crossXs = new List<Intersection>(); double slope = 0, y = s1.Y; slope = (s2.Y - s1.Y) / (s1.X - s2.X);//s2.Y == s1.Y不单独判断,反正这里可以正常处理s2.Y == s1.Y即slope==0 var shearedPolyC = linkC.Select(r => new Vertex(r.X, r.X * slope + r.Y) as VertexBase).ToList();//为了保存错切计算的坐标 y = s1.X * slope + s1.Y; var minX = s1.X > s2.X ? s2.X : s1.X; var maxX = s1.X > s2.X ? s1.X : s2.X; //LinkedListNode<VertexBase> vertex; int i = -1; var backToHead = false; for (var vertex = linkC.First; //这样回到头部的线也可以正常被切到 vertex != null && ((vertex.Value is Vertex && vertex.Next != null) || ((vertex.Value is Intersection) && ((Intersection)vertex.Value).NextC != null) || (vertex.Value is Vertex && vertex.Next == null && !backToHead) || (vertex.Value is Intersection && ((Intersection)vertex.Value).NextC == null && !backToHead)); vertex = vertex.Next) { ++i; var c1 = shearedPolyC[i % shearedPolyC.Count]; var c2 = shearedPolyC[(i + 1) % shearedPolyC.Count]; // 重合 if (c1.Y == c2.Y && c1.Y == y) continue; //不相交 if (c1.Y > y && c2.Y > y) continue; if (c1.Y < y && c2.Y < y) continue; var x = LineCrossH(y, c1, c2); var npy = y - x * slope; var inters = new Intersection(x, npy); VertexBase next = null; if ((x > minX && x < maxX) || (c2.Y == y && x == s2.X) || (x == minX && c1.Y != y && c2.Y != y) || (x == maxX && c1.Y != y && c2.Y != y)) { inters.Name = "I" + Counter.Default.Val++; if (vertex.Next == null) { backToHead = true; next = linkC.First.Value; } else { next = vertex.Next.Value; } WindowLog.Default.Log("切割C的边{0}{1}得到交点{2}", vertex.Value.Name, next.Name, inters.Name); inters.NextC = next; if (vertex.Value is Vertex) ((Vertex)vertex.Value).Next = inters; else if (vertex.Value is Intersection) ((Intersection)vertex.Value).NextC = inters; linkC.AddAfter(vertex, inters); vertex = vertex.Next; crossXs.Add(inters); } if (backToHead) break; #region log var cLinkSb = new StringBuilder(); var v = linkC.First.Value; while (v != null) { cLinkSb.Append(v.Name); if (v is Intersection) { var curr = v as Intersection; next = curr.NextC; } else if (v is Vertex) { var curr = v as Vertex; next = curr.Next; } if (next.Equals(linkC.First.Value)) { break; } v = next; cLinkSb.Append("->"); } WindowLog.Default.Log("C链表:" + cLinkSb); #endregion } return crossXs; }