コード例 #1
0
ファイル: math3d_capsule.py プロジェクト: xjsansan/pyMath3D
class Capsule(object):
    def __init__(self, point_a, point_b, radius):
        self.line_segment = LineSegment(point_a, point_b)
        self.radius = radius

    def clone(self):
        return Capsule(self.line_segment.point_a, self.line_segment.point_b,
                       self.radius)

    def length(self):
        return self.line_segment.length()

    def volume(self):
        return math.pi * self.radius * self.radius * (
            (4.0 / 3.0) * self.radius + self.length())

    def calc_line(self):
        return self.line_segment.calc_line()

    def contains_point(self, point, eps=1e-7):
        return True if self.line_segment.point_distance(
            point) < self.radius + eps else False

    def make_mesh(self, subdivision_level=1):
        pass  # TODO: Use convex hull generator algorithm after computing points.
コード例 #2
0
 def split_triangle(min_area):
     for triple in self.triangle_list:
         triangle = self.make_triangle(triple)
         for i in range(3):
             edge = LineSegment(point_a=triangle[i],
                                point_b=triangle[i + 1])
             for j, vertex in enumerate(self.vertex_list):
                 if (vertex - edge.point_a).length() < eps:
                     continue
                 if (vertex - edge.point_b).length() < eps:
                     continue
                 if not edge.contains_point(vertex, eps=eps):
                     continue
                 self.triangle_list.remove(triple)
                 self.triangle_list.append(
                     (j, triple[(i + 2) % 3], triple[i]))
                 self.triangle_list.append(
                     (j, triple[(i + 1) % 3], triple[(i + 2) % 3]))
                 min_area['area'] = min(
                     self.make_triangle(self.triangle_list[-2]).area(),
                     min_area['area'])
                 min_area['area'] = min(
                     self.make_triangle(self.triangle_list[-1]).area(),
                     min_area['area'])
                 return True
コード例 #3
0
 def intersect_with(self, other, eps=1e-7):
     if isinstance(other, Triangle):
         from math3d_point_cloud import PointCloud
         point_cloud = PointCloud()
         for line_segment in self.yield_line_segments():
             point = other.intersect_with(line_segment)
             if point is not None:
                 point_cloud.add_point(point)
         for line_segment in other.yield_line_segments():
             point = self.intersect_with(line_segment)
             if point is not None:
                 point_cloud.add_point(point)
         point_list = point_cloud.point_list
         if len(point_list) == 2:
             line_segment = LineSegment(point_list[0], point_list[1])
             if line_segment.length() >= eps:
                 return line_segment
         elif len(point_list) > 0:
             return point_cloud
     elif isinstance(other, LineSegment):
         plane = self.calc_plane()
         alpha = plane.intersect_line_segment(other)
         if alpha is not None and 0.0 <= alpha <= 1.0:
             point = other.lerp(alpha)
             if self.contains_point(point, eps):
                 return point
コード例 #4
0
ファイル: math3d_cylinder.py プロジェクト: xjsansan/pyMath3D
class Cylinder(object):
    def __init__(self, point_a, point_b, radius):
        self.line_segment = LineSegment(point_a, point_b)
        self.radius = radius

    def clone(self):
        return Cylinder(self.line_segment.point_a, self.line_segment.point_b,
                        self.radius)

    def length(self):
        return self.line_segment.length()

    def calc_line(self):
        return self.line_segment.calc_line()

    def contains_point(self, point, eps=1e-7):
        spine = self.line_segment.point_b - self.line_segment.point_a
        unit_normal = spine.normalized()
        vector = point - self.line_segment.point_a
        length = vector.dot(unit_normal)
        if length <= -eps or length >= spine.length() + eps:
            return False
        hypotenuse = vector.length()
        distance = math.sqrt(hypotenuse * hypotenuse - length * length)
        return True if distance < self.radius + eps else False

    def make_mesh(self, subdivision_level=1):
        from math3d_point_cloud import PointCloud
        from math3d_transform import AffineTransform
        spine = self.line_segment.point_b - self.line_segment.point_a
        spine_length = spine.length()
        transform = AffineTransform().make_frame(spine,
                                                 self.line_segment.point_a)
        count = 4 * (subdivision_level + 1)
        point_cloud = PointCloud()
        for i in range(count):
            angle = 2.0 * math.pi * float(i) / float(count)
            vertex = Vector(self.radius * math.cos(angle),
                            self.radius * math.sin(angle), 0.0)
            point_cloud.point_list.append(transform(vertex))
            point_cloud.point_list.append(
                transform(vertex + Vector(0.0, 0.0, spine_length)))
        return point_cloud.find_convex_hull()
コード例 #5
0
    def split_against_plane(self, plane, eps=1e-7):
        back_list = []
        front_list = []

        triangle_list = [self.clone()]
        while len(triangle_list) > 0:

            triangle = triangle_list.pop(0)

            side_list = [plane.side(triangle[i], eps) for i in range(3)]
            if all([side == Side.NEITHER for side in side_list]):
                pass
            elif all([
                    side == Side.BACK or side == Side.NEITHER
                    for side in side_list
            ]):
                back_list.append(triangle)
            elif all([
                    side == Side.FRONT or side == Side.NEITHER
                    for side in side_list
            ]):
                front_list.append(triangle)
            else:
                for i in range(3):
                    if (side_list[i] == Side.BACK
                            and side_list[(i + 1) % 3] == Side.FRONT
                            or side_list[i] == Side.FRONT
                            and side_list[(i + 1) % 3] == Side.BACK):
                        # This might not be the best tessellation, but it will work.
                        line_segment = LineSegment(triangle[i],
                                                   triangle[i + 1])
                        alpha = plane.intersect_line_segment(line_segment)
                        point = line_segment.lerp(alpha)
                        triangle_list.append(
                            Triangle(triangle[i], point, triangle[i + 2]))
                        triangle_list.append(
                            Triangle(point, triangle[i + 1], triangle[i + 2]))
                        break

        return back_list, front_list
コード例 #6
0
ファイル: math3d_capsule.py プロジェクト: xjsansan/pyMath3D
 def __init__(self, point_a, point_b, radius):
     self.line_segment = LineSegment(point_a, point_b)
     self.radius = radius
コード例 #7
0
 def yield_line_segments(self):
     yield LineSegment(self.point_a, self.point_b)
     yield LineSegment(self.point_b, self.point_c)
     yield LineSegment(self.point_c, self.point_a)