Face FaceTree() { int faceID = reader.ReadInt32(); if (faceID == -1) return null; int startVertex1ID = reader.ReadInt32(); int startVertex2ID = reader.ReadInt32(); int edgeCount = reader.ReadInt32(); Face face = new Face(0); face.ID = faceID; faceIDDict[face.ID] = face; for (int i = 0; i < edgeCount; i++) { int edgeID = reader.ReadInt32(); face.AddEdge(edgeIDDict[edgeID]); } face.StartVertex1 = vertexIDDict[startVertex1ID]; face.StartVertex2 = vertexIDDict[startVertex2ID]; face.LeftChild = FaceTree(); face.RightChild = FaceTree(); face.UpdateVertices(); return face; }
public void Initliaze( Face root ) { this.root = root; root.UpdateVertices(); facecellTree = new FacecellTree( root ); this.controller = CloverController.GetInstance(); }
/// <summary> /// 根据给定的长和宽初始化纸张 /// </summary> /// <param name="width"></param> /// <param name="height"></param> public void Initialize(float width, float height) { Vertex.Vertex_count = 0; Face.Face_count = 0; Edge.Edge_count = 0; faceLayer = new FaceLayer(); edgeLayer = new EdgeLayer(); vertexLayer = new VertexLayer(); // Create 4 original vertices Vertex[] vertices = new Vertex[4]; vertices[0] = new Vertex(-width / 2, height / 2, 0); vertices[1] = new Vertex(-width / 2, -height / 2, 0); vertices[2] = new Vertex(width / 2, -height / 2, 0); vertices[3] = new Vertex(width / 2, height / 2, 0); // 初始化纹理坐标 vertices[0].u = 0; vertices[0].v = 0; vertices[1].u = 0; vertices[1].v = 1; vertices[2].u = 1; vertices[2].v = 1; vertices[3].u = 1; vertices[3].v = 0; // add to vertex layer foreach (Vertex v in vertices) { vertexLayer.InsertVertex(v); renderController.AddVisualInfoToVertex(v); } // create a face Face face = new Face(0); // creates 4 edges Edge[] edges = new Edge[4]; // create one face and four edges for (int i = 0; i < 4; i++) { edges[i] = new Edge(vertices[i], vertices[i + 1 < 4 ? i + 1 : 0]); EdgeTree tree = new EdgeTree(edges[i]); edgeLayer.AddTree(tree); face.AddEdge(edges[i]); edges[i].Face1 = face; } // use root to initialize facecell tree and lookuptable faceLayer.Initliaze(face); face.UpdateVertices(); faceLayer.UpdateLeaves(); faceGroupLookupTable = new FaceGroupLookupTable(face); // 此处也应该拍一张快照 SnapshotNode node = new SnapshotNode(faceLayer.Leaves); // 为了方便revert设计,详情联系 ET node.Type = SnapshotNodeKind.CutKind; node.OriginVertexListCount = vertexLayer.VertexCellTable.Count; node.OriginEdgeListCount = edgeLayer.Count; shadowSystem.Snapshot(node); // 调用渲染层,更新纸张 CreatePaper(face); }
/// <summary> /// 切割一个面为两个面 /// </summary> /// <param name="face">要切割的面</param> /// <param name="edge">割线,不一定要在边层里面的边,只要两个端点的坐标在面的边上即可</param> /// <returns>被边引用的割线</returns> Edge CutFace(Face face, Edge edge) { Debug.Assert(edge != null); if (edge == null) { throw new System.ArgumentNullException(); } CloverController controller = CloverController.GetInstance(); RenderController render = controller.RenderController; VertexLayer vertexLayer = controller.VertexLayer; //ShadowSystem shadowSystem = controller.ShadowSystem; Vertex newVertex1 = edge.Vertex1.Clone() as Vertex; Vertex newVertex2 = edge.Vertex2.Clone() as Vertex; Vertex newVertexOld1 = newVertex1; Vertex newVertexOld2 = newVertex2; // 生成一个面的周围的顶点的环形表 face.UpdateVertices(); List<Vertex> vertexList = new List<Vertex>(); vertexList.AddRange(face.Vertices); int count = vertexList.Count + 1; while (true) { if ( ( !CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), vertexList[1].GetPoint3D()) && CloverMath.IsPointInTwoPoints(newVertex1.GetPoint3D(), vertexList[0].GetPoint3D(), vertexList[1].GetPoint3D(), 0.001) ) || ( !CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), vertexList[1].GetPoint3D()) && CloverMath.IsPointInTwoPoints(newVertex2.GetPoint3D(), vertexList[0].GetPoint3D(), vertexList[1].GetPoint3D(), 0.001) ) ) { break; } vertexList.Add(vertexList[0]); vertexList.RemoveAt(0); // 防止死循环 if (count-- == 0) return null; } vertexList.Add(vertexList[0]); // 要被分割的边 Edge beCutEdge1 = null; Edge beCutEdge2 = null; // 原始边 List<Edge> rangeA = new List<Edge>(); List<Edge> rangeB = new List<Edge>(); // 分割出来的子面 Face f1 = new Face(face.Layer); Face f2 = new Face(face.Layer); face.LeftChild = f1; face.RightChild = f2; List<Edge> currentEdgeList = null; for (int i = 0; i < vertexList.Count - 1; i++) { Edge currentEdge = CloverTreeHelper.FindEdge(face, vertexList[i], vertexList[i + 1]); // 割线过顶点 if (CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), vertexList[i].GetPoint3D(), 0.1)) { currentEdgeList = rangeA; newVertex1 = vertexList[i]; } else if (CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), vertexList[i].GetPoint3D(), 0.1)) { currentEdgeList = rangeB; newVertex2 = vertexList[i]; } // 割线过边 else if (CloverMath.IsPointInTwoPoints(newVertex1.GetPoint3D(), vertexList[i].GetPoint3D(), vertexList[i + 1].GetPoint3D(), 0.001) && !CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), vertexList[i + 1].GetPoint3D(), 0.1)) { currentEdgeList = rangeA; beCutEdge1 = currentEdge; Edge cutEdge1 = null; Edge cutEdge2 = null; // 两个孩子为空,新建两条边 if (beCutEdge1.LeftChild == null && beCutEdge1.RightChild == null) { // 没人用过的共边 Debug.Assert(newVertex1 != null); // 分割一条边生成两条新的边 cutEdge1 = new Edge(vertexList[i], newVertex1); cutEdge2 = new Edge(newVertex1, vertexList[i + 1]); beCutEdge1.LeftChild = cutEdge1; beCutEdge1.RightChild = cutEdge2; rangeB.Add(cutEdge1); rangeA.Add(cutEdge2); cutEdge1.Face1 = f2; cutEdge2.Face1 = f1; } else { // 对于已经割过的边,我们“必须”使用它原来的顶点 if (CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), beCutEdge1.LeftChild.Vertex1.GetPoint3D())) { newVertex1 = beCutEdge1.LeftChild.Vertex1; } else if (CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), beCutEdge1.LeftChild.Vertex2.GetPoint3D())) { newVertex1 = beCutEdge1.LeftChild.Vertex2; } else if (CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), beCutEdge1.RightChild.Vertex1.GetPoint3D())) { newVertex1 = beCutEdge1.RightChild.Vertex1; } else if (CloverMath.IsTwoPointsEqual(newVertex1.GetPoint3D(), beCutEdge1.RightChild.Vertex2.GetPoint3D())) { newVertex1 = beCutEdge1.RightChild.Vertex2; } else { System.Windows.MessageBox.Show("fuck2"); return null; } if (CloverMath.IsTwoPointsEqual(vertexList[i].GetPoint3D(), beCutEdge1.LeftChild.Vertex1.GetPoint3D(), 0.001) || CloverMath.IsTwoPointsEqual(vertexList[i].GetPoint3D(), beCutEdge1.LeftChild.Vertex2.GetPoint3D(), 0.001)) { rangeB.Add(beCutEdge1.LeftChild); rangeA.Add(beCutEdge1.RightChild); beCutEdge1.LeftChild.Face2 = f2; beCutEdge1.RightChild.Face2 = f1; } else { rangeA.Add(beCutEdge1.LeftChild); rangeB.Add(beCutEdge1.RightChild); beCutEdge1.LeftChild.Face2 = f1; beCutEdge1.RightChild.Face2 = f2; } } // 计算newVertex1和newVertex2的纹理坐标 CalculateTexcoord(newVertex1, beCutEdge1); continue; } else if (CloverMath.IsPointInTwoPoints(newVertex2.GetPoint3D(), vertexList[i].GetPoint3D(), vertexList[i + 1].GetPoint3D(), 0.001) && !CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), vertexList[i + 1].GetPoint3D(), 0.1)) { currentEdgeList = rangeB; beCutEdge2 = currentEdge; // 两个孩子为空,新建两条边 if (beCutEdge2.LeftChild == null && beCutEdge2.RightChild == null) { Debug.Assert(newVertex2 != null); // 分割一条边生成两条新的边 Edge cutEdge1 = new Edge(vertexList[i], newVertex2); Edge cutEdge2 = new Edge(newVertex2, vertexList[i + 1]); beCutEdge2.LeftChild = cutEdge1; beCutEdge2.RightChild = cutEdge2; rangeA.Add(cutEdge1); rangeB.Add(cutEdge2); cutEdge1.Face1 = f1; cutEdge2.Face1 = f2; } else { // 对于已经割过的边,我们“必须”使用它原来的顶点 if (CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), beCutEdge2.LeftChild.Vertex1.GetPoint3D())) { newVertex2 = beCutEdge2.LeftChild.Vertex1; } else if (CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), beCutEdge2.LeftChild.Vertex2.GetPoint3D())) { newVertex2 = beCutEdge2.LeftChild.Vertex2; } else if (CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), beCutEdge2.RightChild.Vertex1.GetPoint3D())) { newVertex2 = beCutEdge2.RightChild.Vertex1; } else if (CloverMath.IsTwoPointsEqual(newVertex2.GetPoint3D(), beCutEdge2.RightChild.Vertex2.GetPoint3D())) { newVertex2 = beCutEdge2.RightChild.Vertex2; } else { System.Windows.MessageBox.Show("f**k"); return null; } if (CloverMath.IsTwoPointsEqual(vertexList[i].GetPoint3D(), beCutEdge2.LeftChild.Vertex1.GetPoint3D(), 0.001) || CloverMath.IsTwoPointsEqual(vertexList[i].GetPoint3D(), beCutEdge2.LeftChild.Vertex2.GetPoint3D(), 0.001)) { rangeA.Add(beCutEdge2.LeftChild); rangeB.Add(beCutEdge2.RightChild); beCutEdge2.LeftChild.Face2 = f1; beCutEdge2.RightChild.Face2 = f2; } else { rangeB.Add(beCutEdge2.LeftChild); rangeA.Add(beCutEdge2.RightChild); beCutEdge2.LeftChild.Face2 = f2; beCutEdge2.RightChild.Face2 = f1; } } // 计算newVertex1和newVertex2的纹理坐标 CalculateTexcoord(newVertex2, beCutEdge2); continue; } currentEdgeList.Add(currentEdge); } Edge newEdge = new Edge(newVertex1, newVertex2); controller.EdgeLayer.AddTree(new EdgeTree(newEdge)); // 是否是新的顶点 if (newVertex1 == newVertexOld1) { vertexLayer.InsertVertex(newVertex1); render.AddVisualInfoToVertex(newVertex1); } if (newVertex2 == newVertexOld2) { vertexLayer.InsertVertex(newVertex2); render.AddVisualInfoToVertex(newVertex2); } // 更新新边的Faces指针 newEdge.Face1 = f1; newEdge.Face2 = f2; // 给两个新面加新的边 rangeA.Add(newEdge); rangeB.Add(newEdge); foreach (Edge e in rangeA) { f1.AddEdge(e); } foreach (Edge e in rangeB) { f2.AddEdge(e); } // 更新两个新面的法向量标杆 f1.StartVertex1 = newVertex2; f1.StartVertex2 = newVertex1; f2.StartVertex1 = newVertex1; f2.StartVertex2 = newVertex2; // 更新面的都为顶点的顺序 f1.UpdateVertices(); f2.UpdateVertices(); // 更新渲染层的部分 render.Delete(face); render.New(f1); render.New(f2); controller.FaceLayer.UpdateLeaves(); return newEdge; }
//public Point[] GetIntersectionPoints( Geometry g1, Geometry g2 ) //{ // Geometry og1 = g1.GetWidenedPathGeometry( new Pen( Brushes.Black, 1.0 ) ); // Geometry og2 = g2.GetWidenedPathGeometry( new Pen( Brushes.Black, 1.0 ) ); // CombinedGeometry cg = new CombinedGeometry( GeometryCombineMode.Intersect, og1, og2 ); // PathGeometry pg = cg.GetFlattenedPathGeometry(); // Point[] result = new Point[ pg.Figures.Count ]; // for ( int i = 0; i < pg.Figures.Count; i++ ) // { // Rect fig = new PathGeometry( new PathFigure[] { pg.Figures[ i ] } ).Bounds; // result[ i ] = new Point( fig.Left + fig.Width / 2.0, fig.Top + fig.Height / 2.0 ); // } // return result; //} /// <summary> /// 判断两个面是否位于同一个平面上 /// </summary> /// <param name="f1"></param> /// <param name="f2"></param> /// <returns></returns> public static bool IsInSamePlane( Face f1, Face f2, double ErrorMargin = 0.00001 ) { double A1, B1, C1, D1; double A2, B2, C2, D2; f1.UpdateVertices(); f2.UpdateVertices(); A1 = f1.Normal.X; A2 = f2.Normal.X; B1 = f1.Normal.Y; B2 = f2.Normal.Y; C1 = f1.Normal.Z; C2 = f2.Normal.Z; D1 = -( f1.Vertices[ 0 ].X * A1 + f1.Vertices[ 0 ].Y * B1 + f1.Vertices[ 0 ].Z * C1 ); D2 = -( f1.Vertices[ 0 ].X * A2 + f1.Vertices[ 0 ].Y * B2 + f1.Vertices[ 0 ].Z * C2 ); if ( ( Math.Abs( A1 * B2 - A2 * B1 ) < ErrorMargin ) && ( Math.Abs( B1 * C2 - B2 * C1 ) < ErrorMargin ) && ( Math.Abs( C1 * D2 - C2 * D1 ) < ErrorMargin ) ) { return true; } else return false; }