예제 #1
0
 def test_cylinder_centroids(self):
     for (r, h, n) in [(10, 100, 50)]:
         m = mesh.Mesh()
         mesh.primitives.add_cylinder(m, r, h, n)
         v = mesh.Vector(0, 0, h / 2)
         self.assertAlmostEqualVector(m.solid_centroid(), v)
         self.assertAlmostEqualVector(m.surface_centroid(), v)
예제 #2
0
 def test_cube_centroids(self):
     m = mesh.Mesh()
     mesh.primitives.add_cube(m, 100)
     centroid0 = mesh.Vector(50.0, 50.0, 50.0)
     centroid1 = m.solid_centroid()
     centroid2 = m.surface_centroid()
     self.assertAlmostEqualVector(centroid1, centroid0)
     self.assertAlmostEqualVector(centroid2, centroid0)
예제 #3
0
 def test_sphere_centroids(self):
     m = mesh.Mesh()
     v = mesh.Vector(23, 45, 67)
     mesh.primitives.add_sphere(m,
                                2.0,
                                origin=v,
                                model="octa",
                                detail_level=3)
     self.assertAlmostEqualVector(m.solid_centroid(), v)
     self.assertAlmostEqualVector(m.surface_centroid(), v)
예제 #4
0
 def test_torus_centroids(self):
     m = mesh.Mesh()
     v = mesh.Vector(1, 2, 3)
     mesh.primitives.add_torus(m, 3, 1, 20, 20, offset=v)
     self.assertAlmostEqualVector(m.solid_centroid(), v)
     self.assertAlmostEqualVector(m.surface_centroid(), v)
예제 #5
0
def intersect(m1, m2):
    '''Compute the intersection of m1 and m2.

    :returns: A new mesh with m2 cut out of m1.
    '''

    # check the algorithm assumptions are satisfied
    if not m1.closed():
        raise ValueError("Mesh 'm1' is not a closed surface")

    if not m2.closed():
        raise ValueError("Mesh 'm2' is not a closed surface")

    # algorithm:

    # classify vertices in m1 into inside and outside m2
    # classify vertices in m2 into inside and outside m1

    # for each face in m1
    # for each face in m2
    # if there is an intersection, record the intersection line

    # output all vertices
    # where intersections exists, add extra vertices

    # for each face in m1 and m2
    # if intersections are recorded
    # partition the face along the intersection lines
    # if a partition contains an original vertex included in the output,
    # output the partition
    # recursively classify paritions to output based on crossing of
    # intersections
    # for each partition to output
    # output the face, triangulating if necessary

    new_vertices = {}
    new_name = {0: 0}  # hack to be visible in the inner function

    m1_vertices = {}
    m2_vertices = {}
    include_vertex = {}

    # determine if m1 vertex is inside or outside m2
    for v in m1.vertices:
        count = 0
        # XXX: this is going to break at some point! Fix with octrees
        p = [
            v,
            v.normal() + mesh.Vector(uniform(-0.1, 0.1), uniform(-0.1, 0.1),
                                     uniform(-0.1, 0.1))
        ]
        for f2 in m2.faces:

            vs = f2.vertices
            s = mesh.triangle_segment_intersect(p, vs, 1)

            if isinstance(s, mesh.Vector):
                count += 1

        if count % 2 == 0:  # even number of crossing => outside
            m1_vertices[v] = 1
        else:
            m1_vertices[v] = 0

    # determine if m2 vertex is inside or outside m1
    for v in m2.vertices:
        count = 0
        # XXX: this is going to break at some point! Fix with octrees
        p = [
            v,
            v.normal() + mesh.Vector(uniform(-0.1, 0.1), uniform(-0.1, 0.1),
                                     uniform(-0.1, 0.1))
        ]
        for f1 in m1.faces:

            vs = f1.vertices
            s = mesh.triangle_segment_intersect(p, vs, 1)

            if isinstance(s, mesh.Vector):
                count += 1

        if count % 2 == 0:  # even number of crossing => outside
            m2_vertices[v] = 0
        else:
            m2_vertices[v] = 1

    # add vertices to the new vertex list, reusing existing vertices
    # if extant
    def add_vertex(v, include):
        s = [k for k, ve in new_vertices.iteritems() if ve == v]

        if len(s) == 0:
            new_vertices[new_name[0]] = v
            include_vertex[new_name[0]] = include
            r = new_name[0]
            new_name[0] += 1
        elif len(s) > 1:
            raise ValueError("Should be at most 1 point")
        else:
            r = s[0]

        return r

    # create Polygons to represent faces
    m1_polygons = {}
    for f1 in m1.faces:
        m1_polygons[f1] = {}
        (vs, u, v, undo) = f1.project2d()
        #vs.reverse()
        p = mesh.Polygon((vs, [(0, 2), (2, 1), (1, 0)]))
        m1_polygons[f1]["p"] = p
        m1_polygons[f1]["u"] = u
        m1_polygons[f1]["v"] = v
        m1_polygons[f1]["undo"] = undo

        # add vertices and record mapping
        m1_polygons[f1]["map"] = []
        for i in range(3):
            m1_polygons[f1]["map"].append(
                add_vertex(f1.vertices[i], m1_vertices[f1.vertices[i]]))

    m2_polygons = {}
    for f2 in m2.faces:
        m2_polygons[f2] = {}
        (vs, u, v, undo) = f2.project2d()
        p = mesh.Polygon((vs, [(0, 2), (2, 1), (1, 0)]))
        m2_polygons[f2]["p"] = p
        m2_polygons[f2]["u"] = u
        m2_polygons[f2]["v"] = v
        m2_polygons[f2]["undo"] = undo

        # add vertices and record mapping
        m2_polygons[f2]["map"] = []
        for i in range(3):
            m2_polygons[f2]["map"].append(
                add_vertex(f2.vertices[i], m2_vertices[f2.vertices[i]]))

    # determine all face/face intersections
    # XXX: optimise this using octrees
    for f1 in m1.faces:

        for f2 in m2.faces:

            s = mesh.triangle_triangle_intersect(list(f2.vertices),
                                                 list(f1.vertices))

            if isinstance(s, list):
                # these two faces intersect
                # add the vertices to the list

                # marry vertices with existing vertices
                for i_s in range(len(s)):
                    s[i_s] = add_vertex(s[i_s], 2)

                u1 = m1_polygons[f1]["u"]
                v1 = m1_polygons[f1]["v"]
                u2 = m2_polygons[f2]["u"]
                v2 = m2_polygons[f2]["v"]

                # record m1 and m2 vertices
                verts1 = [0] * len(s)
                verts2 = [0] * len(s)
                for i_s in range(len(s)):
                    verts1[i_s] = m1_polygons[f1]["p"].add_vertex(
                        new_vertices[s[i_s]].project2dvector(u1, v1))
                    #if verts1[i_s].name == len(m1_polygons[f1]["map"]):
                    m1_polygons[f1]["map"].append(s[i_s])
                    #elif verts1[i_s].name > len(m1_polygons[f1]["map"]):
                    #    raise ValueError

                    verts2[i_s] = m2_polygons[f2]["p"].add_vertex(
                        new_vertices[s[i_s]].project2dvector(u2, v2))
                    #if verts2[i_s].name == len(m2_polygons[f2]["map"]):
                    m2_polygons[f2]["map"].append(s[i_s])
                    #elif verts2[i_s].name > len(m2_polygons[f2]["map"]):
                    #    raise ValueError

                # record m1 and m2 lines
                for i_s in range(len(s) - 1):
                    m1_polygons[f1]["p"].add_line(verts1[i_s - 1], verts1[i_s])
                    m2_polygons[f2]["p"].add_line(verts2[i_s - 1], verts2[i_s])

    # create new output mesh
    m = mesh.Mesh()

    # add all the vertices
    nv = []
    for k, v in new_vertices.items():
        if include_vertex[k]:
            nv.append(m.add_vertex(v))
        else:
            nv.append(v)

    print "output"

    # output faces for the outer mesh
    output_faces(m1_polygons, include_vertex, new_vertices, m, nv)
    # output faces for the inner mesh
    output_faces(m2_polygons, include_vertex, new_vertices, m, nv, True)

    return m