Exemplo n.º 1
0
    /// <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);
    }
Exemplo n.º 2
0
    /// <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);
    }