Example #1
0
def _get_edge_bridges(polygon, z_plane, min_bridges, average_distance,
                      avoid_distance):
    def is_near_list(point_list, point, distance):
        for p in point_list:
            if pdist(p, point) <= distance:
                return True
        return False

    lines = polygon.get_lines()
    poly_lengths = polygon.get_lengths()
    num_of_bridges = max(min_bridges,
                         int(round(sum(poly_lengths) / average_distance)))
    real_average_distance = sum(poly_lengths) / num_of_bridges
    max_line_index = poly_lengths.index(max(poly_lengths))
    positions = []
    current_line_index = max_line_index
    distance_processed = poly_lengths[current_line_index] / 2
    positions.append(current_line_index)
    while len(positions) < num_of_bridges:
        current_line_index += 1
        current_line_index %= len(poly_lengths)
        # skip lines that are not at least twice as long as the grid width
        while (distance_processed + poly_lengths[current_line_index] <
               real_average_distance):
            distance_processed += poly_lengths[current_line_index]
            current_line_index += 1
            current_line_index %= len(poly_lengths)
        positions.append(current_line_index)
        distance_processed += poly_lengths[current_line_index]
        distance_processed %= real_average_distance
    result = []
    bridge_positions = []
    for line_index in positions:
        position = polygon.get_middle_of_line(line_index)
        # skip bridges that are close to another existing bridge
        if is_near_list(bridge_positions, position, avoid_distance):
            line = polygon.get_lines()[line_index]
            # calculate two alternative points on the same line
            position1 = pdiv(padd(position, line.p1), 2)
            position2 = pdiv(padd(position, line.p2), 2)
            if is_near_list(bridge_positions, position1, avoid_distance):
                if is_near_list(bridge_positions, position2, avoid_distance):
                    # no valid alternative - we skip this bridge
                    continue
                else:
                    # position2 is OK
                    position = position2
            else:
                # position1 is OK
                position = position1
        # append the original position (ignoring z_plane)
        bridge_positions.append(position)
        # move the point to z_plane
        position = (position[0], position[1], z_plane)
        bridge_dir = pnormalized(pcross(lines[line_index].dir,
                                        polygon.plane.n))
        result.append((position, bridge_dir))
    return result
Example #2
0
 def subdivide(self, depth):
     sub = []
     if depth == 0:
         sub.append(self)
     else:
         p4 = pdiv(padd(self.p1, self.p2), 2)
         p5 = pdiv(padd(self.p2, self.p3), 2)
         p6 = pdiv(padd(self.p3, self.p1), 2)
         sub += Triangle(self.p1, p4, p6).subdivide(depth - 1)
         sub += Triangle(p6, p5, self.p3).subdivide(depth - 1)
         sub += Triangle(p6, p4, p5).subdivide(depth - 1)
         sub += Triangle(p4, self.p2, p5).subdivide(depth - 1)
     return sub
Example #3
0
 def reset_cache(self):
     self.minx = min(self.p1[0], self.p2[0], self.p3[0])
     self.miny = min(self.p1[1], self.p2[1], self.p3[1])
     self.minz = min(self.p1[2], self.p2[2], self.p3[2])
     self.maxx = max(self.p1[0], self.p2[0], self.p3[0])
     self.maxy = max(self.p1[1], self.p2[1], self.p3[1])
     self.maxz = max(self.p1[2], self.p2[2], self.p3[2])
     self.e1 = Line(self.p1, self.p2)
     self.e2 = Line(self.p2, self.p3)
     self.e3 = Line(self.p3, self.p1)
     # calculate normal, if p1-p2-pe are in clockwise order
     if self.normal is None:
         self.normal = pnormalized(
             pcross(psub(self.p3, self.p1), psub(self.p2, self.p1)))
     if not len(self.normal) > 3:
         self.normal = (self.normal[0], self.normal[1], self.normal[2], 'v')
     self.center = pdiv(padd(padd(self.p1, self.p2), self.p3), 3)
     self.plane = Plane(self.center, self.normal)
     # calculate circumcircle (resulting in radius and middle)
     denom = pnorm(pcross(psub(self.p2, self.p1), psub(self.p3, self.p2)))
     self.radius = (pdist(self.p2, self.p1) * pdist(self.p3, self.p2) *
                    pdist(self.p3, self.p1)) / (2 * denom)
     self.radiussq = self.radius**2
     denom2 = 2 * denom * denom
     alpha = pdist_sq(self.p3, self.p2) * pdot(psub(
         self.p1, self.p2), psub(self.p1, self.p3)) / denom2
     beta = pdist_sq(self.p1, self.p3) * pdot(psub(
         self.p2, self.p1), psub(self.p2, self.p3)) / denom2
     gamma = pdist_sq(self.p1, self.p2) * pdot(psub(
         self.p3, self.p1), psub(self.p3, self.p2)) / denom2
     self.middle = (self.p1[0] * alpha + self.p2[0] * beta +
                    self.p3[0] * gamma, self.p1[1] * alpha +
                    self.p2[1] * beta + self.p3[1] * gamma,
                    self.p1[2] * alpha + self.p2[2] * beta +
                    self.p3[2] * gamma)
Example #4
0
    def split_line(self, line):
        outer = []
        inner = []
        # project the line onto the polygon's plane
        proj_line = self.plane.get_line_projection(line)
        intersections = []
        for pline in self.get_lines():
            cp, d = proj_line.get_intersection(pline)
            if cp:
                intersections.append((cp, d))
        # sort the intersections by distance
        intersections.sort(key=lambda collision: collision[1])
        intersections.insert(0, (proj_line.p1, 0))
        intersections.append((proj_line.p2, 1))

        def get_original_point(d):
            return padd(line.p1, pmul(line.vector, d))

        for index in range(len(intersections) - 1):
            p1, d1 = intersections[index]
            p2, d2 = intersections[index + 1]
            if p1 != p2:
                middle = pdiv(padd(p1, p2), 2)
                new_line = Line(get_original_point(d1), get_original_point(d2))
                if self.is_point_inside(middle):
                    inner.append(new_line)
                else:
                    outer.append(new_line)
        return (inner, outer)
Example #5
0
 def get_outside_lines(poly1, poly2):
     result = []
     for line in poly1.get_lines():
         collisions = []
         for o_line in poly2.get_lines():
             cp, dist = o_line.get_intersection(line)
             if (cp is not None) and (0 < dist < 1):
                 collisions.append((cp, dist))
         # sort the collisions according to the distance
         collisions.append((line.p1, 0))
         collisions.append((line.p2, 1))
         collisions.sort(key=lambda collision: collision[1])
         for index in range(len(collisions) - 1):
             p1 = collisions[index][0]
             p2 = collisions[index + 1][0]
             if pdist(p1, p2) < epsilon:
                 # ignore zero-length lines
                 continue
             # Use the middle between p1 and p2 to check the
             # inner/outer state.
             p_middle = pdiv(padd(p1, p2), 2)
             p_inside = (poly2.is_point_inside(p_middle)
                         and not poly2.is_point_on_outline(p_middle))
             if not p_inside:
                 result.append(Line(p1, p2))
     return result
Example #6
0
 def get_middle_of_line(self, index):
     if (index >= len(self._points)) \
             or (not self.is_closed and index == len(self._points) - 1):
         return None
     else:
         return pdiv(padd(self._points[index], self._points[(index + 1) % len(self._points)]),
                     2)
Example #7
0
def intersect_torus_plane(center, axis, majorradius, minorradius, direction,
                          triangle):
    # take normal to the plane
    n = triangle.normal
    if pdot(n, direction) == 0:
        return (None, None, INFINITE)
    if pdot(n, axis) == 1:
        return (None, None, INFINITE)
    # find place on torus where surface normal is n
    b = pmul(n, -1)
    z = axis
    a = psub(b, pmul(z, pdot(z, b)))
    a_sq = pnormsq(a)
    if a_sq <= 0:
        return (None, None, INFINITE)
    a = pdiv(a, sqrt(a_sq))
    ccp = padd(padd(center, pmul(a, majorradius)), pmul(b, minorradius))
    # find intersection with plane
    (cp, l) = triangle.plane.intersect_point(direction, ccp)
    return (ccp, cp, l)