public void Initialize(float width, float height) { // 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); // add to vertex layer foreach (Vertex v in vertices) { vertexLayer.InsertVertex(v); } // create a face Face face = new Face(); // 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]); } // use root to initialize facecell tree and lookuptable faceLayer.Initliaze(face); }
public void EnterFoldingMode(Vertex pickedVertex, Face nearestFace) { this.cloverController = CloverController.GetInstance(); // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为baseFace this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace); if (this.group == null) { System.Windows.MessageBox.Show("找不到Groups"); return; } this.pickedVertex = pickedVertex; this.baseFace = nearestFace; foreach (Face face in group.GetFaceList()) { if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < baseFace.Layer) baseFace = face; } // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组 foreach (Face face in group.GetFaceList()) { if (face.Layer >= baseFace.Layer) this.facesAboveBase.Add(face); else this.facesBelowBase.Add(face); } // 保存pickedVertex的原始位置 originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z); }
public List<Face> EnterTuckingMode(Vertex pickedVertex, Face nearestFace) { this.cloverController = CloverController.GetInstance(); //cloverController.ShadowSystem.CheckUndoTree(); // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为floorFace,最上面的那个面作为ceilingFace this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace); this.pickedVertex = pickedVertex; this.floorFace = this.ceilingFace = nearestFace; // 是正向还是反向 Vector3D currNormal = group.Normal * cloverController.RenderController.Entity.Transform.Value; Double judge = Vector3D.DotProduct(currNormal, new Vector3D(0, 0, 1)); isPositive = judge < 0 ? false : true; if (isPositive) { foreach (Face face in group.GetFaceList()) { if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < floorFace.Layer) floorFace = face; if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > ceilingFace.Layer) ceilingFace = face; } // 将同Group的面分为在floor和ceiling之间和在floor和ceiling之外两组 foreach (Face face in group.GetFaceList()) { if (face.Layer >= floorFace.Layer && face.Layer <= ceilingFace.Layer) this.facesInHouse.Add(face); else this.facesNotInHouse.Add(face); } } else { foreach (Face face in group.GetFaceList()) { if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > floorFace.Layer) floorFace = face; if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < ceilingFace.Layer) ceilingFace = face; } // 将同Group的面分为在floor和ceiling之间和在floor和ceiling之外两组 foreach (Face face in group.GetFaceList()) { if (face.Layer <= floorFace.Layer && face.Layer >= ceilingFace.Layer) this.facesInHouse.Add(face); else this.facesNotInHouse.Add(face); } } // 保存pickedVertex的原始位置 originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z); return facesInHouse; }
/// <summary> /// 返回两面的共边,如果没有则返回null /// </summary> /// <param name="face1"></param> /// <param name="face2"></param> /// <returns></returns> public static Edge GetSharedEdge(Face face1, Face face2) { foreach (Edge edge1 in face1.Edges) { foreach (Edge edge2 in face2.Edges) { if (edge1 == edge2) return edge1; } } return null; }
public List<Face> EnterFoldingMode(Vertex pickedVertex, Face nearestFace) { this.cloverController = CloverController.GetInstance(); //cloverController.ShadowSystem.CheckUndoTree(); // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为baseFace this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace); this.pickedVertex = pickedVertex; this.baseFace = nearestFace; // 是正向还是反向 Vector3D currNormal = group.Normal * cloverController.RenderController.Entity.Transform.Value; Double judge = Vector3D.DotProduct(currNormal, new Vector3D(0, 0, 1)); isPositive = judge < 0 ? false : true; if (isPositive) { foreach (Face face in group.GetFaceList()) { if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < baseFace.Layer) baseFace = face; } // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组 foreach (Face face in group.GetFaceList()) { if (face.Layer >= baseFace.Layer) this.facesAboveBase.Add(face); else this.facesBelowBase.Add(face); } } else { foreach (Face face in group.GetFaceList()) { if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > baseFace.Layer) baseFace = face; } // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组 foreach (Face face in group.GetFaceList()) { if (face.Layer <= baseFace.Layer) this.facesAboveBase.Add(face); else this.facesBelowBase.Add(face); } } // 保存pickedVertex的原始位置 originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z); return facesAboveBase; }
/// <summary> /// 删除looktable的某个face,不存在则会失败返回false /// </summary> /// <param name="f"></param> /// <returns></returns> bool RemoveFace( Face f ) { foreach ( FaceGroup group in faceGroupList ) { if ( group.HasFace( f ) ) { group.RemoveFace( f ); if ( group.Count == 0 ) faceGroupList.Remove( group ); return true; } } return false; }
/// <summary> /// 往lookuptable中加入face,会自动匹配加入group中或新增group。 /// 否则强制新建一个group /// </summary> /// <param name="f"></param> void AddFace( Face f ) { foreach ( FaceGroup fg in faceGroupList ) { if ( fg.HasFace( f ) ) { return; } if ( fg.IsMatch( f ) ) { fg.AddFace( f ); return; } } FaceGroup newfgt = new FaceGroup( f ); faceGroupList.Add( newfgt ); }
public FacecellTree( Face r ) { root = r; }
/// <summary> /// 判断一个3D点是否处在由points围成的平面内 /// </summary> /// <param name="point">要检查的点</param> /// <param name="points">平面的边界</param> /// <returns>返回true如果点在平面内或平面边界上</returns> /// <author>kid</author> public static Boolean IsPointInAreaWithoutEdge(Point3D pe, Face f) { for (int i = 0; i < f.Vertices.Count; i++) { Vector3D v1 = pe - f.Vertices[i].GetPoint3D(); Vector3D v2 = f.Vertices[(i + 1) % f.Vertices.Count].GetPoint3D() - f.Vertices[i].GetPoint3D(); if (Vector3D.DotProduct(v1, v2) <= 0) return false; } return true; }
/// <summary> /// 判断一个点是否在一个面中 /// </summary> /// <param name="vervex"></param> /// <param name="face"></param> /// <returns></returns> public static Boolean IsVertexInFace(Vertex vervex, Face face) { foreach (Vertex v in face.Vertices) { if (v == vervex) return true; } return false; }
/// <summary> /// 创建半透明面 /// </summary> /// <param name="face"></param> public void CreateTransparentFace(Face face) { transparentFaces.Add(face); RenderController render = CloverController.GetInstance().RenderController; render.New(face); render.ToGas(face); }
void Travel(Face root, int ID, ref Face target) { if (root == null) return; if (root.ID == ID) { target = root; return; } Travel(root.LeftChild, ID, ref target); Travel(root.RightChild, ID, ref target); }
bool IsLeave( Face face ) { return face.LeftChild == null && face.RightChild == null; }
/// <summary> /// 更新叶节点 /// </summary> /// <param name="oldFace">改变了的节点</param> /// <remarks>如果输入一个面,则将这个面移除并将他的两个孩子加到叶节点表。否则重建整棵树。</remarks> public void UpdateLeaves( Face oldFace = null ) { if ( oldFace == null ) { leaves.Clear(); Travel( root ); return; } Debug.Assert( oldFace.LeftChild != null && oldFace.RightChild != null ); leaves.Remove( oldFace ); leaves.Add( oldFace.LeftChild ); leaves.Add( oldFace.RightChild ); }
/// <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; }
/// <summary> /// 自动在折纸过程中旋转摄像机 /// </summary> /// <param name="beRotatedFaceList"></param> private void AutoCamera(Face face) { // 自动旋转摄像头 Vector3D vector1 = face.Normal; Vector3D vector2 = new Vector3D(0, 0, 1); Quaternion quat; if (vector1 == new Vector3D(0, 0, 1)) quat = new Quaternion(); else if (vector1 == new Vector3D(0, 0, -1)) quat = new Quaternion(new Vector3D(0, 1, 0), 180); else { Vector3D axis = Vector3D.CrossProduct(vector1, vector2); axis.Normalize(); Double deg = Vector3D.AngleBetween(vector1, vector2); quat = new Quaternion(axis, deg); } renderController.BeginRotationSlerp(quat); }
/// <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">初始的face</param> public void CreatePaper(Face face) { if (model != null) { renderController.DeleteAll(); } // 初始化模型 renderController.InitializeRenderController(); renderController.New(face); model = renderController.Entity; // 初始化纹理 ImageBrush imb = new ImageBrush(); imb.ImageSource = new BitmapImage(new Uri(@"media/paper/paper1.jpg", UriKind.Relative)); DiffuseMaterial mgf = new DiffuseMaterial(imb); DiffuseMaterial mgb = new DiffuseMaterial(new SolidColorBrush(Colors.OldLace)); renderController.FrontMaterial = mgf; renderController.BackMaterial = mgb; }
/// <summary> /// 判断两个面是否相连,即有无公共边 /// </summary> /// <param name="f1"></param> /// <param name="f2"></param> /// <returns></returns> public static bool IsTwoFaceConected(Face f1, Face f2) { foreach (Edge e1 in f1.Edges) { foreach (Edge e2 in f2.Edges) { if (e1 == e2) return true; } } return false; }
public void Initliaze( Face root ) { this.root = root; root.UpdateVertices(); facecellTree = new FacecellTree( root ); this.controller = CloverController.GetInstance(); }
public void UpdateLeaves( Face oldFace = null ) { facecellTree.UpdateLeaves( oldFace ); }
/// <summary> /// 后续遍历 /// </summary> /// <param name="r">根节点</param> /// <remarks>请在调用Travel前清空leaves!</remarks> void Travel( Face r ) { if ( r == null ) return; Travel( r.LeftChild ); Travel( r.RightChild ); if ( IsLeave( r ) ) leaves.Add( r ); }
/// <summary> /// 判断一个面是否在一个组中 /// </summary> /// <param name="face"></param> /// <param name="group"></param> /// <returns></returns> public static Boolean IsFaceInGroup(Face face, FaceGroup group) { // 等待杨旭瑜写完group,。。。 // todo return false; }
/// <summary> /// 计算两个face的二面角 /// </summary> /// <param name="f1"></param> /// <param name="f2"></param> /// <returns></returns> public static double CalculatePlaneAngle(Face f1, Face f2) { // 找出面面交线的方向向量 Vector3D intersectionlinevec = Vector3D.CrossProduct(f1.Normal, f2.Normal); // 两个平面平行时候 if (intersectionlinevec.Length == 0) { return 0.0; } // 找出与面垂直的分割面 Vector3D cutFacenor = Vector3D.CrossProduct(intersectionlinevec, f1.Normal); double A = cutFacenor.X; double B = cutFacenor.Y; double C = cutFacenor.Z; double D = 0; Point3D p = new Point3D(); foreach (Edge e in f1.Edges) { Vector3D ve = e.Vertex2.GetPoint3D() - e.Vertex1.GetPoint3D(); if (IsTwoVectorTheSameDir(ve, cutFacenor)) { p = e.Vertex1.GetPoint3D(); break; } } D = -(cutFacenor.X * p.X + cutFacenor.Y * p.Y + cutFacenor.Z * p.Z); // 检测两个面的夹角是钝角还是锐角 bool IsObtuseAngle = false; foreach (Vertex vertice1 in f1.Vertices) { foreach (Vertex vertice2 in f2.Vertices) { double space1 = A * vertice1.X + B * vertice1.Y + C * vertice1.Z + D; double space2 = A * vertice2.X + B * vertice2.Y + C * vertice2.Z + D; if (space1 * space2 < 0) { IsObtuseAngle = true; break; } } if (IsObtuseAngle) { break; } } // 可以开始计算二面角了 double cosAngle = Vector3D.DotProduct(f1.Normal, f2.Normal); cosAngle = cosAngle / (f1.Normal.Length * f2.Normal.Length); double angle = Math.Acos(Math.Abs(cosAngle)); if (IsObtuseAngle) { return Math.PI - angle; } return angle; }
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; }
/// <summary> /// 得到面所在的分组,如果获取失败返回null,当获取失败时检查一下是否忘记add了。 /// </summary> /// <param name="f"></param> /// <returns></returns> public FaceGroup GetGroup( Face f ) { foreach ( FaceGroup fg in faceGroupList ) { if ( fg.GetFaceList().Contains( f ) ) return fg; } return null; }
/// <summary> /// 构造第一个面的时候初始化。 /// </summary> /// <param name="f"></param> public FaceGroupLookupTable( Face f ) { FaceGroup g = new FaceGroup( f ); faceGroupList.Add( g ); }
/// <summary> /// 判断一个3D点是否处在由points围成的平面内 /// </summary> /// <param name="point">要检查的点</param> /// <param name="points">平面的边界</param> /// <returns>返回true如果点在平面内或平面边界上</returns> /// <author>kid</author> public static Boolean IsPointInArea(Point3D pe, Face f) { foreach (Vertex v in f.Vertices) { if (AreTwoPointsSameWithDeviation(pe, v.GetPoint3D())) return true; } Vector3D lastN = new Vector3D(0, 0, 0); for (int i = 0; i < f.Vertices.Count; i++) { Point3D p1 = f.Vertices[i].GetPoint3D(); Point3D p2 = f.Vertices[(i + 1) % f.Vertices.Count].GetPoint3D(); Vector3D v1 = pe - p1; Vector3D v2 = p2 - pe; Vector3D currN = Vector3D.CrossProduct(v1, v2); if (currN.Length < 0.0001) { if (IsPointInTwoPoints(pe, p1, p2)) return true; else return false; } if (Vector3D.DotProduct(currN, lastN) < 0) return false; lastN = currN; } // for (int i = 0; i < f.Vertices.Count; i++) // { // Vector3D v1 = pe - f.Vertices[i].GetPoint3D(); // Vector3D v2 = f.Vertices[(i + 1) % f.Vertices.Count].GetPoint3D() - f.Vertices[i].GetPoint3D(); // if (Vector3D.DotProduct(v1, v2) < 0) // return false; // } return true; }
public void AddTuckingAction(List<Face> faceList, List<Face> rotatedFace, List<Face> fixedFace, Edge edge, Face ceilingFace, Face floorFace, bool isPositive) { ActionCore(faceList, rotatedFace, fixedFace, edge, isPositive); string scripts = ""; scripts += "ceilingFace = clover.FindFacesByID(" + ceilingFace.ID.ToString() + ")\r\n"; scripts += "floorFace = clover.FindFacesByID(" + floorFace.ID.ToString() + ")\r\n"; scripts += "clover.UpdateTableAfterTucking(ceilingFace, floorFace, edge, " + (isPositive ? "True" : "False") + ")\r\n"; scripts += "clover.AntiOverlap()\r\n"; totalScript += scripts; writer.Write(scripts); writer.Flush(); }
public List<Face> GetFaceExcludeGroupFoundByFace( Face f ) { List<Face> result = new List<Face>(); FaceGroup excludefg = GetGroup( f ); foreach ( FaceGroup fg in faceGroupList ) { if ( fg != excludefg ) { foreach ( Face face in fg.GetFaceList() ) { result.Add( f ); } } } return result; }