/// <summary> /// Build open influence region with 3 faces for a given edge. /// </summary> /// <param name="edge">The given edge.</param> /// <param name="edges">All existing edges.</param> /// <param name="ap1">Allowed point 1</param> /// <param name="ap2">Allowed point 2</param>s /// <param name="innerPoints">Points that approximately lie inside the influence region (polyhedron).</param> /// <returns>The polyhedron.</returns> private ConvexPolyhedron BuildPolyhedron2(Edge edge, Dictionary <Edge, Edge> edges, out int ap1, out int ap2, out List <int> innerPoints) { buildPCounter++; ap1 = -1; ap2 = -1; int i = edge.vertex1; int j = edge.vertex2; int k = edge.vertex3; // check if the i and j vertices are chosen correctly if (Vector3.Dot(Vector3.Cross(PointCloud[k].Position - PointCloud[i].Position, PointCloud[k].Position - PointCloud[j].Position), edge.normal) < 0) { i = edge.vertex2; j = edge.vertex1; } // positions of i, j and k Vector3 ip = PointCloud[i].Position; Vector3 jp = PointCloud[j].Position; Vector3 kp = PointCloud[k].Position; Vector3 n1 = Vector3.Cross(edge.normal, jp - ip).normalized; Vector3 n3 = (Vector3.Cross(n1 + Mathf.Tan(Mathf.Deg2Rad * regionAngle) * (ip - jp).normalized, edge.normal)).normalized; Vector3 n2 = Vector3.Cross(edge.normal, n1 + Mathf.Tan(Mathf.Deg2Rad * regionAngle) * (jp - ip).normalized).normalized; float s = sMult * (float)Math.Max(PointCloud[i].UniformityDegree, PointCloud[j].UniformityDegree) * (PointCloud[i].MinEdge + PointCloud[j].MinEdge) / 2; ConvexPolyhedron polyhedron = new ConvexPolyhedron(); polyhedron.AddFace(n1, ip); polyhedron.AddFace(n2, ip); polyhedron.AddFace(n3, jp); polyhedron.AddFace(-n1, s * -n1 + (ip + jp) / 2); polyhedron.AddFace(edge.normal, ip + s * edge.normal); // top face polyhedron.AddFace(-edge.normal, ip - s * edge.normal); // bottom face - innerPoints = VoxelSet.GetInnerPoints(polyhedron, false, influenceRegion2, (ip + jp) / 2); Vector3?pLeft = null, pRight = null; float minAngleLeft = 181f, minAngleRight = 181f; foreach (var point in innerPoints) { if (point == i || point == j) { continue; } Edge left = new Edge(point, i, Vector3.back); Edge right = new Edge(point, j, Vector3.back); if (edges.ContainsKey(left)) { float angleLeft = Vector3.Angle(ip - jp, PointCloud[point].Position - ip); if (angleLeft < minAngleLeft) { minAngleLeft = angleLeft; pLeft = PointCloud[point].Position; ap1 = point; } } if (edges.ContainsKey(right)) { float angleRight = Vector3.Angle(jp - ip, PointCloud[point].Position - jp); if (angleRight < minAngleRight) { minAngleRight = angleRight; pRight = PointCloud[point].Position; ap2 = point; } } } ConvexPolyhedron p = new ConvexPolyhedron(); p.AddFace(n1, ip); if (pLeft == null) { p.AddFace(n2, ip); } else { p.AddFace(Vector3.Cross((Vector3)pLeft - ip, edge.normal).normalized, ip); } if (pRight == null) { p.AddFace(n3, jp); } else { p.AddFace(-Vector3.Cross((Vector3)pRight - jp, edge.normal).normalized, jp); } polyhedron.AddFace(-n1, s * -n1 + (ip + jp) / 2); return(p); }
/// <summary> /// Build an influence region of the given edge. /// </summary> /// <param name="edge">The edge, which influence region to be foind.</param> /// <param name="edges">The set of existing edges.</param> /// <returns>Polyhedron object that is the influence region.</returns> private ConvexPolyhedron BuildPolyhedron(Edge edge, Dictionary <Edge, Edge> edges, out int ap1, out int ap2, out List <int> innerPoints) { if (influenceRegion2) { return(BuildPolyhedron2(edge, edges, out ap1, out ap2, out innerPoints)); } buildPCounter++; ap1 = -1; ap2 = -1; int i = edge.vertex1; int j = edge.vertex2; int k = edge.vertex3; // check if the i and j vertices are chosen correctly if (Vector3.Dot(Vector3.Cross(PointCloud[k].Position - PointCloud[i].Position, PointCloud[k].Position - PointCloud[j].Position), edge.normal) < 0) { i = edge.vertex2; j = edge.vertex1; } // positions of i, j and k Vector3 ip = PointCloud[i].Position; Vector3 jp = PointCloud[j].Position; Vector3 kp = PointCloud[k].Position; // the size of the polyhedron float s = (float)Math.Max(PointCloud[i].UniformityDegree, PointCloud[j].UniformityDegree) * (PointCloud[i].MinEdge + PointCloud[j].MinEdge) / 2; // bary center of the triangle ijk Vector3 p = (ip + jp + kp) / 3; // center of the edge ij Vector3 p_m = (ip + jp) / 2; // normal of the triangle (polygon) ijk Vector3 N = edge.normal; ConvexPolyhedron polyhedron = new ConvexPolyhedron(); Vector3 n1 = Vector3.Cross(edge.normal, jp - ip).normalized; polyhedron.AddFace(n1, ip); // test polyhedron.AddFace(N, p_m + 2 * s * N); // top face polyhedron.AddFace(-N, p_m - 2 * s * N); // bottom face - polyhedron.AddFace(-Vector3.Cross(N, ip - p).normalized, ip); // face containing pi - polyhedron.AddFace(Vector3.Cross(N, jp - p).normalized, jp); // face containing pj Vector3 N5 = Vector3.Cross(jp - ip, N).normalized; polyhedron.AddFace(N5, p_m + s * N5); // here it checks whether there are some edges inside the influnce region // that are connected to i or j var points = VoxelSet.GetInnerPoints(polyhedron, smartUpdate, influenceRegion2, p_m); Vector3?pLeft = null, pRight = null; //float minAngleLeft = 181f, minAngleRight = 181f; float minAngleLeft = 90 + regionAngle, minAngleRight = 90 + regionAngle; foreach (var point in points) { if (point == i || point == j) { continue; } Edge left = new Edge(point, i, Vector3.back); Edge right = new Edge(point, j, Vector3.back); if (edges.ContainsKey(left)) { float angleLeft = Vector3.Angle(jp - ip, PointCloud[point].Position - ip); if (angleLeft < minAngleLeft) { minAngleLeft = angleLeft; pLeft = PointCloud[point].Position; ap1 = point; } } if (edges.ContainsKey(right)) { float angleRight = Vector3.Angle(ip - jp, PointCloud[point].Position - jp); if (angleRight < minAngleRight) { minAngleRight = angleRight; pRight = PointCloud[point].Position; ap2 = point; } } } // additional faces that we need to hold geometry integrity if (pLeft != null) { polyhedron.AddFace(-Vector3.Cross(N, (Vector3)pLeft - ip).normalized, ip); } if (pRight != null) { polyhedron.AddFace(Vector3.Cross(N, (Vector3)pRight - jp).normalized, jp); } innerPoints = points; return(polyhedron); }