Линия между 2 плоскими секциями (секциями крыши) - вершина или долина - PullRequest
0 голосов
/ 04 июля 2019

Я пытаюсь создать секции крыши для типового здания для печати на 3D-принтере.

У меня есть 3D-точки для углов нижней части каждой секции крыши. Я могу рассчитать угол между двумя соседними плоскостями.

Мне нужен угол между двумя плоскими секциями, если смотреть сверху. Если этот угол больше 180 градусов, это пик. Меньше 180 - это долина.

#!/usr/bin/python2.7
import math

nfmt = '5.1'
fuzz = .001

class Point(object):
    """ Class for 3d point object
    """
    def __init__(self,x,y,z):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)

    def __sub__(self, other):
        if isinstance(other, (int, float)):
            return Point(self.x - other, self.y - other, self.z - other)
        elif isinstance(other, Point):
            return Point(self.x - other.x, self.y - other.y, self.z - other.z)
        else:
            raise TypeError("Cannot subtract Point and {0}".format(type(other)))

    def __str__(self):
        return '({0:{prec}f},{1:{prec}f},{2:{prec}f})'.format(self.x, self.y,self.z,  prec=nfmt)

    def __iter__(self):
        return self.tuple().__iter__()

    def tuple(self):
        return (self.x, self.y, self.z)

class Plane(object):

    def __init__(self,p1,p2,p3):
        pt1 = p2 - p1
        pt2 = p3 - p1
        self.a = pt1.y * pt2.z - pt2.y * pt1.z
        self.b = pt2.x * pt1.z - pt1.x * pt2.z
        self.c = pt1.x * pt2.y - pt1.y * pt2.x
        self.d = (-self.a * p1.x - self.b * p1.y - self.c * p1.z)
        # reduce parameters
        x = sum([abs(self.a),abs(self.b),abs(self.c)])/3
        self.a /= x
        self.b /= x
        self.c /= x
        self.d /= x


    def dihedral(self,other):
        if not isinstance(other,Plane):
            raise TypeError('dihedral requires a Plane argument')
        d  = self.a*other.a + self.b*other.b + self.c*other.c
        e1 = math.sqrt(self.a*self.a + self.b*self.b + self.c*self.c)
        e2 = math.sqrt(other.a*other.a + other.b*other.b + other.c*other.c)
        d  = d / (e1 * e2)
        return math.degrees(math.acos(d))

    def __str__(self):
        return '{0:{prec}f} X + {1:{prec}f} Y + {2:{prec}f} Z + {3:{prec}f} = 0'.format(self.a, self.b,self.c, self.d,  prec=nfmt)



## Points for each roof
B0pts = [Point(54.50,54.50, 7.13),Point(44.50,54.50,12.91),Point(44.50,31.50,12.91),
         Point(38.50,25.50,16.37),Point(54.50, 9.50, 7.13),Point(54.50,54.50, 7.13)]

R2pts = [Point(36.00,54.50, 8.00),Point(44.50,54.50,12.91),Point(44.50,31.50,12.91),
         Point(36.00,40.00, 8.00),Point(36.00,54.50, 8.00)]

L0pts = [Point(36.00,40.00, 8.00),Point(44.50,31.50,12.91),Point(38.50,25.50,16.37),
         Point(14.50,25.50,16.37),Point( 0.00,40.00, 8.00),Point(36.00,40.00, 8.00)]

F3pts = [Point(36.00,54.50, 8.00),Point(36.00,40.00, 8.00),Point(-1.50,40.00, 8.00),
         Point(-1.50,54.50, 8.00),Point(36.00,54.50, 8.00)]

""" [[common line],angle degrees
B0xR2 common line (( 44.5, 54.5, 12.9),( 44.5, 31.5, 12.9)) dihedral 120.00 Peak
B0xL0 common line (( 44.5, 31.5, 12.9),( 38.5, 25.5, 16.4)) dihedral 138.59 Peak
L0xR2 common line (( 36.0, 40.0,  8.0),( 44.5, 31.5, 12.9)) dihedral  41.41 Valley
F3xL0 common line (( 36.0, 40.0,  8.0),( -1.5, 40.0,  8.0)) dihedral  30.00 Valley

"""

B0 = Plane(*B0pts[0:3])
R2 = Plane(*R2pts[0:3])
L0 = Plane(*L0pts[0:3])
F3 = Plane(*F3pts[0:3])

print '\nDihedrals'
print 'B0xR2 Peak   dihedral %7.2f' % B0.dihedral(R2)  #prints 119.96
print 'B0xL0 Peak   dihedral %7.2f' % B0.dihedral(L0)  #prints 138.56
print 'L0xR2 Valley dihedral %7.2f' % L0.dihedral(R2)  #prints  41.39
print 'F3xL0 Valley dihedral %7.2f' % F3.dihedral(L0)  #prints  29.99

Показанный угол находится между двумя плоскостями (не плоскими сечениями). Присоединение показано должно быть B0xR2 120 240 Peak B0xL0 139 221 Пик L0xR2 41 151 Долина F3xL0 30 120 Долина

...