Пример #1
0
    def smoothing(self):
        for i in range(self.num_iterations):
            for n in self.grid.Nodes:
                neighbours = []
                assert len(n.edges) > 1
                for e in n.edges:
                    assert len(e.nodes) == 2
                    n1 = e.nodes[0]
                    n2 = e.nodes[1]
                    if n1 == n:
                        neighbours.append(n2)
                    else:
                        neighbours.append(n1)

                laplacian = Vector()
                for neighbour_node in neighbours:
                    laplacian.sum(point_to_vector(neighbour_node.as_point()))
                laplacian.dev(len(neighbours))
                laplacian.sub(point_to_vector(n.as_point()))
                backward_laplacian = deepcopy(laplacian)

                laplacian.mul(self.lamb)
                backward_laplacian.mul(self.mu)
                backward_laplacian.mul(-1)

                if i % 2 == 0:
                    Smoothing.move_node(self, n, laplacian)
                else:
                    Smoothing.move_node(self, n, backward_laplacian)

            Smoothing.write_grid_and_print_info(self, i)
Пример #2
0
    def smoothing(self):
        Smoothing.write_grid_and_print_info(self, 0)
        for i in range(1, self.num_iterations):
            laplacians = []
            fazzians = []
            for n in self.grid.Nodes:
                m = len(n.faces)
                w = [f.area() for f in n.faces]
                N = self.create_matrix_of_normals(n)

                dv = self.vector_to_avg_of_centroids(
                    n, self.n_neighbours_for_border_nodes)

                assert N.shape == (m, 3)
                assert len(w) == m
                assert isinstance(dv, Vector)

                W = diag(w)
                NTW = dot(N.T, W)
                A = dot(NTW, N)
                assert W.shape == (m, m)
                assert NTW.shape == (3, m)
                assert A.shape == (3, 3)

                eigenValues, eigenVectors = eig(A)
                idx = eigenValues.argsort()[::-1]
                eigenValues = eigenValues[idx]
                eigenVectors = eigenVectors[:, idx]

                assert abs(det(A) - cumprod(eigenValues)[-1]) < DETERMINANT_ACCURACY, \
                    print(det(A), cumprod(eigenValues)[-1])

                k = sum((eigenValues > self.epsilon * eigenValues[0]))
                ns = eigenVectors[:, k:]
                dv = dv.coords_np_array().reshape(3, 1)

                assert ns.shape == (3, 3 - k), 'Wrong eigenvectors shape'
                assert dv.shape == (3, 1), 'Wrong shape'
                # self.print_info(n, eigenValues, ns, k)
                if k < 3:
                    ttT = dot(ns, ns.T)
                    if n.fixed:
                        t = self.st * dot(ttT, dv)
                    else:
                        t = self.st * dot(ttT, dv)
                    assert t.shape == (3, 1), 'Wrong shift shape'
                    laplacian = Vector(float(t[0, 0]), float(t[1, 0]),
                                       float(t[2, 0]))
                else:
                    laplacian = Vector(0, 0, 0)
                laplacians.append(laplacian)

            Smoothing.apply_laplacians(self, laplacians)

            FuzzyVectorMedian(self.grid).smoothing()

            Smoothing.write_grid_and_print_info(self, i)
 def area(self):
     """Calculate the area of the face."""
     assert len(self.nodes) == 3, "Wrong number of nodes in the face"
     n1, n2, n3 = self.nodes[0], self.nodes[1], self.nodes[2]
     p1, p2, p3 = n1.as_point(), n2.as_point(), n3.as_point()
     v1 = Vector.subtract_vectors(point_to_vector(p1),
                                  (point_to_vector(p2)))
     v2 = Vector.subtract_vectors(point_to_vector(p1),
                                  (point_to_vector(p3)))
     res = cross_product(v1, v2).norm() / 2
     assert isinstance(res, float), print('Wrong area', res)
     return res
 def normal(self):
     assert len(self.nodes) == 3, 'Wrong number of nodes in the face'
     p1 = self.nodes[0].as_point()
     p2 = self.nodes[1].as_point()
     p3 = self.nodes[2].as_point()
     v1 = Vector(p1.x, p1.y, p1.z)
     v2 = Vector(p2.x, p2.y, p2.z)
     v3 = Vector(p3.x, p3.y, p3.z)
     vf = Vector.subtract_vectors(v1, v2)
     vs = Vector.subtract_vectors(v1, v3)
     vr = cross_product(vf, vs)
     vr.make_unit()
     assert isinstance(vr, Vector)
     vr.mul(-1)
     return vr
Пример #5
0
    def is_node_fixed(n):
        border_edges = [e for e in n.edges if e.border]
        assert len(border_edges) == 2, print('Wrong number of border edges',
                                             len(border_edges))

        alpha = 0.01
        be1_v = border_edges[0]
        be2_v = border_edges[1]
        # make vectors directed in different sides.
        # represent as (n1) --be1_v-- (n2) --be2_v-- (n3)
        n1 = None
        n2 = n
        n3 = None
        assert len(be1_v.nodes) == 2
        assert len(be2_v.nodes) == 2
        if be1_v.nodes[0] == n:
            n1 = be1_v.nodes[1]
        else:
            n1 = be1_v.nodes[0]
            assert be1_v.nodes[1] == n

        if be2_v.nodes[0] == n:
            n3 = be2_v.nodes[1]
        else:
            n3 = be2_v.nodes[0]
            assert be2_v.nodes[1] == n

        assert n1 is not n2
        assert n2 is not n3
        assert n3 is not n1

        n1_v = Vector(n1.x, n1.y, n1.z)
        n2_v = Vector(n2.x, n2.y, n2.z)
        n3_v = Vector(n3.x, n3.y, n3.z)
        be1 = Vector.subtract_vectors(n1_v, n2_v)
        be2 = Vector.subtract_vectors(n3_v, n2_v)
        be1.make_unit()
        be2.make_unit()
        dot_between_unit_edges = dot_product(be1, be2)
        assert -1 <= dot_between_unit_edges <= 1
        if dot_between_unit_edges > (-1 + alpha):
            return True, border_edges

        return False, border_edges
Пример #6
0
    def vector_to_avg_of_centroids(self, node, n_neighbours=None):
        dv = Vector()
        p = point_to_vector(node.as_point())
        weights = 0

        # turn off condition len(node.faces) % 2 != 0 for a second
        if node.fixed:
            neighbours = self.find_n_neighbours_faces_of_node(
                node, n_neighbours)
        else:
            neighbours = node.faces

        assert len(neighbours) > 0
        assert isinstance(node.Id, int)

        for f in neighbours:
            #self.grid.adj_list_for_border_nodes[node.Id - 1, f.Id] = 1
            c = point_to_vector(f.centroid())
            c.sub(p)

            if self.weight_faces_by_angle:
                weight = self.set_weight_for_face(node, f, c)
            else:
                weight = 1.0

            assert isinstance(c, Vector)
            assert isinstance(weight, float)
            c.mul(weight)
            dv.sum(c)
            weights += weight
        dv.dev(weights)
        return dv
def test_dot():
    v1 = Vector(1, 1, 1)
    v2 = Vector(1, 1, 1)
    assert dot_product(v1, v2) == 3, 'Wrong dot product'

    v1 = Vector(0, 0, 0)
    v2 = Vector(0, 0, 0)
    assert dot_product(v1, v2) == 0, 'Wrong dot product'

    v1 = Vector(-1, 0, 1)
    v2 = Vector(2, 1, -1)
    assert dot_product(v1, v2) == -3, 'Wrong dot product'

    v1 = Vector(0.5, 4, -1)
    v2 = Vector(2, 3, 1)
    assert dot_product(v1, v2) == 12, 'Wrong dot product'
Пример #8
0
 def build_first_room(self):
     for corridor in self.corridors:
         print(corridor)
     """ Initialize dungeon by putting the first structure in queue """
     directions = [Vector(d) for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]]
     locations = [
         self.origin + l for l in [[0, 1], [0, -1], [1, 0], [-1, 0]]
     ]
     for i in range(len(directions)):
         length = 6
         #print("creating corridor: start=%s, direction=%s, length%s"%(locations[i], directions[i], length))
         self.make_corridor(locations[i], directions[i], length)
         self.plan_construction(self.periodic,
                                location=locations[i] +
                                length * directions[i],
                                direction=directions[i])
Пример #9
0
    def laplacian(self, node):
        neighbours = []
        assert len(node.edges) > 1
        for e in node.edges:
            assert len(e.nodes) == 2
            n1 = e.nodes[0]
            n2 = e.nodes[1]
            if n1 == node:
                neighbours.append(n2)
            else:
                neighbours.append(n1)

        laplacian = Vector()
        for neighbour_node in neighbours:
            laplacian.sum(point_to_vector(neighbour_node.as_point()))
        laplacian.dev(len(neighbours))
        laplacian.sub(point_to_vector(node.as_point()))
        return laplacian
Пример #10
0
    def border_edge_to_project_on(self, n, shift_vector):
        is_fixed, border_edges = self.is_node_fixed(n)

        if self.fix_corner_nodes and is_fixed:
            return Vector(0, 0, 0)

        dot_products_between_edges_and_shift = [
            dot_product(edge_to_vector(e), shift_vector) for e in border_edges
        ]
        edge_to_project_on_number = argmax(
            dot_products_between_edges_and_shift)
        assert edge_to_project_on_number == 0 or edge_to_project_on_number == 1
        edge_to_project_on = edge_to_vector(
            border_edges[edge_to_project_on_number])
        edge_to_project_on.make_unit()
        assert isinstance(edge_to_project_on, Vector)
        return edge_to_project_on
def test_cross():
    v1 = Vector(1, 1, 1)
    v2 = Vector(1, 1, 1)
    assert cross_product(v1, v2).x == 0, 'Wrong cross product'
    assert cross_product(v1, v2).y == 0, 'Wrong cross product'
    assert cross_product(v1, v2).z == 0, 'Wrong cross product'

    v1 = Vector(-1, 4, 19)
    v2 = Vector(1.5, 5, -3)
    assert cross_product(v1, v2).x == -107, 'Wrong cross product'
    assert cross_product(v1, v2).y == 25.5, 'Wrong cross product'
    assert cross_product(v1, v2).z == -11, 'Wrong cross product'

    v1 = Vector(-1, -1, -13)
    v2 = Vector(-32, -1, -12.4)
    assert cross_product(v1,
                         v2).x == -0.5999999999999996, 'Wrong cross product'
    assert cross_product(v1, v2).y == 403.6, 'Wrong cross product'
    assert cross_product(v1, v2).z == -31, 'Wrong cross product'
def test_vector():
    v = Vector()
    v2 = Vector(1, 0.1, -1)
    assert v.coords() == (0, 0, 0), "Wrong vector initialization"
    v.sum(v2)
    assert v.coords() == (1, 0.1, -1), 'Wrong vector sum'
    v.sub(v2)
    assert v.coords() == (0, 0, 0), 'Wrong subtraction'
    v.sum(v2)
    assert v.coords() == (1, 0.1, -1), print('Wrong vector sum', v.coords())
    v.mul(3.1)
    assert v.coords() == (3.1, 0.31000000000000005,
                          -3.1), print('Wrong vector multiplication',
                                       v.coords())
    v.dev(2)
    assert v.coords() == (1.55, 0.15500000000000003,
                          -1.55), print('Wrong vector division', v.coords())
Пример #13
0
    def smoothing(self):
        """Performs smoothing using FVM."""
        for it in range(self.num_iterations):

            for f in self.grid.Faces:
                f.fuzzy_median = f.normal()

            self.define_fvs()
            self.fuzzy_vector_medians()

            laplacians = []
            for n in self.grid.Nodes:
                laplacian = Vector()
                if n.fixed:
                    for e in n.edges:
                        i = e.nodes[0]
                        j = e.nodes[1]

                        if i == n:
                            pass
                        else:
                            assert j == n
                            j = e.nodes[0]
                            i = e.nodes[1]

                        i = i.as_point()
                        j = j.as_point()

                        assert 0 < len(e.faces) < 3

                        aux_vector = Vector()
                        for f in e.faces:
                            assert f.fuzzy_median is not None
                            diff = Vector.subtract_vectors(
                                point_to_vector(j), point_to_vector(i))

                            dot = dot_product(f.fuzzy_median, diff)
                            fm = deepcopy(f.fuzzy_median)

                            assert abs(fm.norm() - 1.0) < EPSILON, print(
                                fm.norm())

                            fm.mul(dot)
                            aux_vector.sum(fm)

                        laplacian.sum(aux_vector)

                    laplacian.mul(self.lambd)
                laplacians.append(laplacian)

            Smoothing.apply_laplacians(self, laplacians)
            Smoothing.write_grid_and_print_info(self, it)
Пример #14
0
    def fuzzy_vector_medians(self, iterations=1):
        """Calculates the fuzzy vector median of all faces in the grid.

        Calculation is based on the formula 10 from
        Shen and Barner,  Fuzzy Vector Median-Based Surface Smoothing.
        """
        for i in range(iterations):
            for f in self.grid.Faces:
                incident_faces = self.incident_faces(f)
                VM = f.vector_median
                sum_r = 0
                res = Vector()
                for iface in incident_faces:
                    R = self.gaussian_membership_function(
                        iface.fuzzy_median, VM)
                    assert isinstance(R, float)
                    sum_r += R
                    aux_vector = deepcopy(iface.fuzzy_median)
                    aux_vector.mul(R)
                    res.sum(aux_vector)

                res.dev(sum_r)

                if res.norm() is not 0.0:
                    res.make_unit()
                else:
                    res = deepcopy(VM)

                assert abs(res.norm() - 1.0) < EPSILON, print(res.norm())

                f.fuzzy_median = res