def __init__(self, pt1, pt2, thickness, dist_from_pt1, height, vertical_vector, polyline2d, close=False): self.close = None epsilon = 0.01 wall = Wall(pt1, pt2, thickness, vertical_vector) bottom_center = Point( [pt1[i] + dist_from_pt1 * wall.matrix[2][i] for i in range(3)]) center = Point([ bottom_center[i] + height * wall.matrix[1][i] - 0.5 * (thickness + epsilon) * wall.matrix[0][i] for i in range(3) ]) frame = Frame([center, wall.matrix]) self.ex = extrude_polyline2d(polyline2d, frame, thickness + epsilon) if close: center = Point([ bottom_center[i] + height * wall.matrix[1][i] - 0.5 * (0.25 * thickness) * wall.matrix[0][i] for i in range(3) ]) frame = Frame([center, wall.matrix]) self.close = extrude_polyline2d(polyline2d, frame, 0.5 * thickness)
def __init__(self, pt1, pt2, wall_thickness, box_thickness, box_offset, dist_from_pt1, height, vertical_vector, polyline2d): epsilon = 0.01 wall = Wall(pt1, pt2, wall_thickness, vertical_vector) bottom_center = Point( [pt1[i] + dist_from_pt1 * wall.matrix[2][i] for i in range(3)]) center = Point([ bottom_center[i] + height * wall.matrix[1][i] + (0.5 * wall_thickness + box_offset) * wall.matrix[0][i] for i in range(3) ]) frame = Frame([center, wall.matrix]) self.ex = extrude_polyline2d(polyline2d, frame, box_thickness)
def center_arc(pt1, pt2, bulge): if bulge > 0.: inc_angle = 4. * np.arctan(bulge) elif bulge < 0.: inc_angle = -4. * np.arctan(bulge) chord = Vector([pt2[i] - pt1[i] for i in range(3)]) mid = Point([0.5 * (pt1[i] + pt2[i]) for i in range(3)]) vec = (chord.norm * 0.5 * bulge * cross(chord, Vector( (0., 0., 1.))).unit()) summit = Point([mid[i] + vec[i] for i in range(3)]) radius = chord.norm / (2. * np.sin(inc_angle / 2.)) vec = radius * Vector([mid[i] - summit[i] for i in range(3)]).unit() center = Point([summit[i] + vec[i] for i in range(3)]) return center
def extrude_polyline2d(polyline, frame, height): pol3d = polyline.to_frame(frame) lines = [] yb_point = Point([frame[0][i] for i in range(3)]) yb_vec = Vector([frame[1][0][i] for i in range(3)]).unit() print '*************' print yb_vec orig = gp_Pnt(frame[0][0], frame[0][1], frame[0][2]) vec = gp_Dir(yb_vec[0], yb_vec[1], yb_vec[2]) plane = gp_Pln(orig, vec) for i, p in enumerate(pol3d[:-1]): print p print 'zob' gp0 = gp_Pnt(p[0], p[1], p[2]) gp1 = gp_Pnt(pol3d[i + 1][0], pol3d[i + 1][1], pol3d[i + 1][2]) lines.append(BRepBuilderAPI_MakeEdge(gp0, gp1).Edge()) wire = BRepBuilderAPI_MakeWire(lines[0]) for l in lines[1:]: wire.Add(l) face = BRepBuilderAPI_MakeFace(wire.Wire()) print 'normal' print[vec.X(), vec.Y(), vec.Z()] extrude = BRepPrimAPI_MakePrism( face.Shape(), gp_Vec(height * vec.X(), height * vec.Y(), height * vec.Z())).Shape() return extrude
def is_on_line(pt, line): c_ref = None s = None for i, coord in enumerate(line[1]): if coord != 0.: s = (pt[i] - line[0][i]) / coord break pt_test = Point([line[0][i] + s * line[1][i] for i in range(3)]) return distance(pt_test, pt) < 1.e-10
def symmetrize(self, smooth=False, plane_normal=Vector([0., 1., 0.])): # we will always take the first point of the control polyline as origin of the symmetry plane new_pol3d = [self.control_polyline[0]] plane = Plane([self.control_polyline[0], plane_normal.unit()]) for p in self.control_polyline[1:]: cp = closest_point_on_plane(p, plane) print 'closest of ' + str(p) + ' is ' + str(cp) vec = Vector([cp[i] - p[i] for i in range(3)]) new_pol3d.append(Point([cp[i] + vec[i] for i in range(3)])) return Spline3D(new_pol3d)
def parameter_frame(tck, s, mode='frenet'): basis = [] t = interpolate.splev(s, tck, der=0) orig = Point([t[0], t[1], t[2]]) if mode == 'frenet': t = interpolate.splev(s, tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) t = interpolate.splev(s, tck, der=2) xpp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T.unit()) B = cross(xp, xpp) basis.append(B.unit()) N = cross(B, T) basis.append(N.unit()) if mode == 'Xnat': t = interpolate.splev(s, tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T) B = cross((1., 0., 0.), T) basis.append(B) N = cross(T, B) basis.append(N) if mode == 'Ynat': t = interpolate.splev(s, tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T) B = cross((0., 1., 0.), T) basis.append(B) N = cross(T, B) basis.append(N) if mode == 'Znat': t = interpolate.splev(s, tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T) B = cross((0., 0., 1.), T) basis.append(B) N = cross(T, B) basis.append(N) matrix = np.zeros((3, 3), dtype=float) for i in range(3): matrix[i] = basis[i] return Frame((orig, matrix))
def named_cartesian_box(xmin=-10., xmax=10., ymin=-10., ymax=10., zmin=-10., zmax=10.): from youbastard.geometry.Polyline3D import Polyline3D from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Sewing, BRepBuilderAPI_MakeSolid from OCC.Core.TopoDS import topods from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox p0 = Point((xmin, ymin, zmin)) p1 = Point((xmin, ymax, zmin)) p2 = Point((xmax, ymax, zmin)) p3 = Point((xmax, ymin, zmin)) p4 = Point((xmin, ymin, zmax)) p5 = Point((xmin, ymax, zmax)) p6 = Point((xmax, ymax, zmax)) p7 = Point((xmax, ymin, zmax)) pol_Xmin = Polyline3D([p0, p1, p5, p4, p0][::-1]) pol_Xmax = Polyline3D([p2, p3, p7, p6, p2][::-1]) pol_Ymin = Polyline3D([p1, p2, p6, p5, p1][::-1]) pol_Ymax = Polyline3D([p0, p4, p7, p3, p0][::-1]) pol_Zmin = Polyline3D([p0, p3, p2, p1, p0][::-1]) pol_Zmax = Polyline3D([p5, p6, p7, p4, p5][::-1]) dicoface = { 'Xmin': face_polyline3d(pol_Xmin).Shape(), 'Xmax': face_polyline3d(pol_Xmax).Shape(), 'Ymin': face_polyline3d(pol_Ymin).Shape(), 'Ymax': face_polyline3d(pol_Ymax).Shape(), 'Zmin': face_polyline3d(pol_Zmin).Shape(), 'Zmax': face_polyline3d(pol_Zmax).Shape() } sew = BRepBuilderAPI_Sewing() make_solid = BRepBuilderAPI_MakeSolid() for k in dicoface.keys(): sew.Add(dicoface[k]) sew.Perform() shell = sew.SewedShape() make_solid.Add(topods.Shell(shell)) box = make_solid.Solid() box = BRepPrimAPI_MakeBox(gp_Pnt(xmin, ymin, zmin), gp_Pnt(xmax, ymax, zmax)) return box, dicoface
def face_polyline(polyline, frame): pol3d = polyline.to_frame(frame) lines = [] yb_point = Point([frame[0][i] for i in range(3)]) yb_vec = Vector([frame[3][i] for i in range(3)]).unit() orig = gp_Pnt(frame[0][0], frame[0][1], frame[0][2]) vec = gp_Dir(yb_vec[0], yb_vec[1], yb_vec[2]) plane = gp_Pln(orig, vec) for i, p in enumerate(pol3d[:-1]): gp0 = gp_Pnt(p[0], p[1], p[2]) gp1 = gp_Pnt(pol3d[i + 1][0], pol3d[i + 1][1], pol3d[i + 1][2]) lines.append(BRepBuilderAPI_MakeEdge(gp0, gp1).Edge()) wire = BRepBuilderAPI_MakeWire(lines[0]) for l in lines[1:]: wire.Add(l) face = BRepBuilderAPI_MakeFace(wire.Wire()) return face.Shape()
def parameter_frame(self, s, mode='frenet'): basis = [] t = interpolate.splev(s, self.tck, der=0) orig = Point([float(t[i]) for i in range(3)]) if mode == 'frenet': t = interpolate.splev(s, self.tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) t = interpolate.splev(s, tck, der=2) xpp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T.unit()) B = cross(xp, xpp) basis.append(B.unit()) N = cross(B, T) basis.append(N.unit()) else: if (type(mode) == Vector): vec = mode.unit() elif mode == 'Xnat': vec = (1., 0., 0.) elif mode == 'Ynat': vec = (0., 1., 0.) elif mode == 'Znat': vec = (0., 0., 1.) t = interpolate.splev(s, self.tck, der=1) xp = Vector([float(t[0]), float(t[1]), float(t[2])]) T = xp.unit() basis.append(T) B = cross(vec, T) basis.append(B) N = cross(T, B) basis.append(N) matrix = [None, None, None] for i in range(3): matrix[i] = [float(basis[i][j]) for j in range(3)] return Frame((orig, matrix))
def parameter_point(self, s): t = interpolate.splev(s, self.tck, der=0) return Point([float(t[i]) for i in range(3)])
def parameter_point(self, s): return Point([self.funcX(s), self.funcY(s), self.funcZ(s)])
from youbastard.geometry.Frame import Frame from youbastard.geometry.Skeleton1D import Skeleton1D from youbastard.io_functions import write_geo import pygmsh as pg from youbastard.modelers.profiles.splineProfileMultiParam import Profile x = [0., -0.125, 0.0, .125] y = [0., 1., 2., 3.] z = [0., 0.125, 0., -0.125] pf = Profile(typ='fon', par=[0.99, 0.1, 0.018, 0.035, 0.001], npt=11) # creation of the 2d profile pol = pf.polyline(closed=True) # TODO : Profile should herit of Polyline_2D geom = pg.built_in.Geometry() a_pt = [Point([x[i], y[i], z[i]]) for i in range(len(x))] from youbastard.geometry.Spline3D import Spline3D spline = Spline3D(a_pt) ndisc = 20 fa = spline.frame_array(mode=Vector([0., 0., 1.]), n=ndisc) for f in fa: pp = pol.to_frame(f, scale=0.2) pp.pop_to_geom(geom) cpol = spline.control_polyline pol_gen = spline.discretize(ndisc) sym = spline.symmetrize()
aft_chordf = lambda s: aft_max_chord * aft_chordfun(s) fore_rot_fun = lin_fun(0.01, 0.2) aft_rot_fun = lin_fun(0.005, 0.12) fore_profile = Profile(typ='fon', par=[0.82, 0.15, 0.02, 0.05, 0.015], npt=7) # creation of the 2d profile aft_profile = Profile(typ='fon', par=[0.69, 0.098, 0.012, 0.017, 0.0025], npt=5) # creation of the 2d profile fin_profile = Profile(typ='fon', par=[0.89, 0.08, 0.0082, 0., 0.], npt=5) # creation of the 2d profile fore_pol = fore_profile.polyline(closed=True) aft_pol = aft_profile.polyline(closed=True) fin_pol = fin_profile.polyline(closed=True) fore_gen_point = [ Point([0., 0., 0.]), Point([0.0, fore_span / 4, 0.002]), Point([0., fore_span / 2, 0.01]), Point([-0.02, 2. * fore_span / 3., 0.015]), Point([-0.08, fore_span, -0.02]) ] deltaX = -0.6 aft_gen_point = [ Point([deltaX, 0., 0.]), Point([deltaX, aft_span / 4, -0.002]), Point([deltaX, aft_span / 2, -0.005]), Point([deltaX - 0.002, 2. * aft_span / 3., -0.008]), Point([deltaX - 0.008, aft_span, 0.006]) ]
matrix_to_quaternion, intersect_2_lines, distance) from youbastard.io_functions import pretty_print from youbastard.geometry.Point import Point from youbastard.geometry.Triangle import Triangle from youbastard.geometry.Line import Line from youbastard.geometry.Vector import Vector from youbastard.geometry.Plane import Plane from youbastard.geometry.Segment import Segment from youbastard.geometry.TreeNode import TreeNode from youbastard.geometry.Quaternion import Quaternion idtest = 1 pretty_print('TEST n.' + str(idtest) + ': TRIANGLE') # create three points p1 = Point((0.01, 0.0, 0.2)) p2 = Point((0.23, 0.5, 0.)) p3 = Point((1., 0.0, 0.)) points = [p1, p2, p3] geo_points = [] # create a triangle t = Triangle(points) pl = Plane(points) print ' ----- A TRIANGLE ------ ' print t print 'attributes' print 'cog = ' + str(t.cg)
from dactylos.modelers.house import Wall, Opening, rectangle, BoxOnWall from dactylos.cad_functions import (show_shapes, extrude_polyline2d, boolean_union, general_fuse_algorithm, general_split_algorithm, face_polyline, big_box, shape_array) from youbastard.geometry.Vector import Vector from youbastard.geometry.Point import Point from youbastard.geometry.Frame import Frame from youbastard.geometry.TreeNode import TreeNode from youbastard.geometry.Polyline2D import Polyline2D from youbastard.geo_functions import distance import json data = { 'points': [ Point([-5., 2.5, 0.]), Point([5., 2.5, 0.]), Point([5., -2.5, 0.]), Point([-5., -2.5, 0.]) ], 'walls': [[0, 1], [1, 2], [2, 3], [3, 0]] } data = {} thick = 0.15 romarine = json.load(open('romarine_cad.json', 'r')) print romarine data['points'] = [] for p in romarine['points']: data['points'].append(Point(p)) data['walls'] = romarine['walls']
print type(pf) # control points of the generatrix global_scale = 0.1 write_polylines_sets('profile', profile = pol) x = [-6., -5., 0., 5., 6.] y = [0., -0.5, -1.5, -0.5, 0.] z = [0.0, 0.,0., 0., -0.00] import pygmsh as pg geom = pg.built_in.Geometry() a_pt = [Point([x[i], y[i], z[i]]) for i in range(len(x))] from youbastard.geometry.Spline3D import Spline3D from youbastard.io_functions import write_geo spline = Spline3D(a_pt) def extrude_along_spline(polyline2d, spline, scale = lambda x: 1., rotation = lambda x: 0., resol = 20): print 'coucou' a_pol3d = None return a_pol3d x = [v * global_scale for v in x] y = [v * global_scale for v in y]
from youbastard.geometry.TreeNode import TreeNode from youbastard.geometry.Point import Point from youbastard.geometry.Vector import Vector from youbastard.geo_functions import distance import numpy as np import matplotlib.pyplot as plt import time r1 = 1. r2 = 1. teta1 = 0.2 teta2 = 0.5 data = {'points': [Point([0., 0., 0.]), Point([r1 * np.cos(teta1), r1 * np.sin(teta1), 0.]), Point([1., 1., 0.]), Point([r2 * np.cos(teta2), r2 * np.sin(teta2), 0.])], 'walls': [[0,1],[0,2], [0,3]]} polylines = [] all_tree_nodes = [] thick = 0.2 for ipoint,point in enumerate(data['points']): sector = [point] for iwall,wall in enumerate(data['walls']): if ipoint in wall: nex=None if wall[0]==ipoint: nex = data['points'][wall[1]] elif wall[1]==ipoint: nex = data['points'][wall[0]] length = distance(point, nex)
def piecewise_bezier_polyline(start_value=0., end_value=0., *largs): import matplotlib.pyplot as plt from youbastard.geometry.Point import Point from youbastard.geometry.Vector import Vector from youbastard.geometry.Line import Line from youbastard.geo_functions import cross, dot, angle, intersect_2_lines prev = [0., start_value] last = [1., end_value] bezier_parts = [[prev]] plt.clf() plt.axis('equal') plt.scatter([prev[0], last[0]], [prev[1], last[1]], c='k') for i, cpl in enumerate(largs[0]): if i == len(largs[0]) - 1: nex = last else: nex = largs[0][i + 1] pt = [cpl[0], cpl[1]] tmppt = Point([pt[0], pt[1], 0.]) plt.scatter(pt[0], pt[1], c='k') rad = cpl[2] vec1 = Vector([pt[0] - prev[0], pt[1] - prev[1], 0.]) vec2 = Vector([nex[0] - pt[0], nex[1] - pt[1], 0.]) Z = Vector([0., 0., 1.]) ang = angle(vec1, vec2, plane_normal=Z) if ang > 0.: sgn = 1. elif ang < 0.: sgn = -1. print ang norm1 = sgn * cross(Z, vec1).unit() norm2 = sgn * cross(Z, vec2).unit() l1 = Line([Point([prev[0], prev[1], 0.]), vec1]) l2 = Line([Point([pt[0], pt[1], 0.]), vec2]) ln1 = Line([ Point([prev[0] + norm1[0] * rad, prev[1] + norm1[1] * rad, 0.]), vec1 ]) ln2 = Line([ Point([nex[0] + norm2[0] * rad, nex[1] + norm2[1] * rad, 0.]), vec2 ]) center_arc = intersect_2_lines(ln1, ln2) if center_arc: cen = [center_arc[j] for j in range(2)] lnorm1 = Line([center_arc, -norm1]) lnorm2 = Line([center_arc, -norm2]) start = intersect_2_lines(lnorm1, l1) end = intersect_2_lines(lnorm2, l2) vecstart = Vector([start[i] - tmppt[i] for i in range(3)]) vecend = Vector([end[i] - tmppt[i] for i in range(3)]) if vecstart.norm > 0.5 * vec1.norm: print 'too long' tmpvec = vecstart.unit() start = Point( [tmppt[i] + 0.5 * vec1.norm * tmpvec[i] for i in range(3)]) if vecend.norm > 0.5 * vec2.norm: tmpvec = vecend.unit() end = Point( [tmppt[i] + 0.5 * vec2.norm * tmpvec[i] for i in range(3)]) bezier_parts[-1].append([start[0], start[1]]) bezier_parts.append([[start[0], start[1]], [pt[0], pt[1]], [end[0], end[1]]]) bezier_parts.append([[end[0], end[1]]]) plt.scatter([start[0], end[0]], [start[1], end[1]], c='g') else: cen = pt bezier_parts[-1].append([pt[0], pt[1]]) bezier_parts.append([[pt[0], pt[1]]]) plt.scatter(cen[0], cen[1], c='r') prev = pt bezier_parts[-1].append([last[0], last[1]]) polx = [] poly = [] for bp in bezier_parts: polx += [p[0] for p in bp] poly += [p[1] for p in bp] plt.plot(polx, poly) def func(parameter): ctpts = None for i, bp in enumerate(bezier_parts): #print parameter,bp[0][0],bp[-1][0], len(bp) if (bp[0][0] <= parameter) and (parameter <= bp[-1][0]): ctpts = bp break s = (parameter - ctpts[0][0]) / (ctpts[-1][0] - ctpts[0][0]) return de_casteljau(ctpts, s)[1] N = 1000 x = [float(i) / float(N - 1) for i in range(N)] fx = [func(s) for s in x] plt.plot(x, fx, '.') plt.show() return func
from dactylos.modelers.house import Wall, Opening, rectangle, BoxOnWall from dactylos.cad_functions import (show_shapes, extrude_polyline2d, boolean_union, general_fuse_algorithm, general_split_algorithm, face_polyline, big_box, shape_array) from youbastard.geometry.Vector import Vector from youbastard.geometry.Point import Point from youbastard.geometry.Frame import Frame from youbastard.geometry.TreeNode import TreeNode from youbastard.geometry.Polyline2D import Polyline2D from youbastard.geo_functions import distance import json data = { 'points': [ Point([-5., 2.5, 0.]), Point([5., 2.5, 0.]), Point([5., -2.5, 0.]), Point([0., 2.5, 0.]), Point([0., -2.5, 0.]), Point([-5., -2.5, 0.]) ], 'walls': [[0, 3], [3, 1], [1, 2], [2, 4], [4, 5], [5, 0], [3, 4]] } thick = 0.15 total_height = 3. floor_frame = Frame([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) ceiling_frame = Frame([[0., 0., total_height], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
from OCC.Core.gp import gp_Pnt from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeVertex from youbastard.analytic_functions.bezier_functions import chord_function from youbastard.geo_functions import distance geom = pg.built_in.Geometry() ndisc = 80 span = 0.8 max_chord = 0.12 scalef = chord_function(0.78) chordf = lambda s: max_chord * scalef(s) a_point = [ Point([0., span / float(ndisc), 0.]), Point([0.01, span / 4, 0.002]), Point([0., span / 2, 0.01]), Point([-0.02, 2. * span / 3., 0.015]), Point([-0.08, span, -0.02]) ] generator = Spline3D(a_point) fa = generator.frame_array(mode=Vector([0., 0., 1.]), n=ndisc) #fa = [Frame([[0.,0.,0.], [[0.,0.,1.],[1.,0.,0.],[0.,1.,0.]]])] + fa shapes = [] generator_extrados = BRepOffsetAPI_ThruSections(False, True) generator_intrados = BRepOffsetAPI_ThruSections(False, True) generator_trailing_edge = BRepOffsetAPI_ThruSections(False, True)
from youbastard.geometry.Point import Point from youbastard.geometry.Vector import Vector from youbastard.geometry.TreeNode import TreeNode from youbastard.geo_functions import distance from youbastard.io_functions import write_polylines_sets data = { 'points': [ Point([-5., 2.5, 0.]), Point([5., 2.5, 0.]), Point([5., -2.5, 0.]), Point([-5., -2.5, 0.]) ], 'walls': [[0, 1], [1, 2], [2, 3], [3, 0]] } data = { 'points': [ Point([0., 0., 0.]), Point([4., 0., 0.]), Point([8., 0., 0.]), Point([11., 0., 0.]), Point([0., 2., 0.]), Point([4., 2., 0.]), Point([6., 2., 0.]), Point([8., 2., 0.]), Point([11., 2., 0.]), Point([0., 5., 0.]), Point([4., 3., 0.]), Point([6., 3., 0.]), Point([6., 5., 0.]),
def intersect_3_planes(p1, p2, p3): A = np.array([p1[:3], p2[:3], p3[:3]]) b = np.array([-p1[3], -p2[3], -p3[3]]).transpose() sol = np.linalg.solve(A, b) return Point([sol[i] for i in range(3)])
aft_max_chord = 0.05 fore_chordfun = chord_function(0.78) aft_chordfun = chord_function(0.9) fore_chordf = lambda s: fore_max_chord * fore_chordfun(s) aft_chordf = lambda s: aft_max_chord * aft_chordfun(s) fore_rot_fun = lin_fun(0.01, 0.2) aft_rot_fun = lin_fun(0.005, 0.12) fore_profile = Profile(typ='fon', par=[0.89, 0.15, 0.05, 0.05, 0.015], npt=17) # creation of the 2d profile aft_profile = Profile(typ='fon', par=[0.69, 0.1, 0.02, 0.02, 0.005], npt=17) # creation of the 2d profile fore_pol = fore_profile.polyline(closed=True) aft_pol = aft_profile.polyline(closed=True) fore_gen_point = [ Point([0., fore_span / float(ndisc), 0.]), Point([0.0, fore_span / 4, 0.002]), Point([0., fore_span / 2, 0.01]), Point([-0.02, 2. * fore_span / 3., 0.015]), Point([-0.08, fore_span, -0.02]) ] deltaX = -0.6 aft_gen_point = [ Point([deltaX, aft_span / float(ndisc), 0.]), Point([deltaX - 0.005, aft_span / 4, -0.002]), Point([deltaX, aft_span / 2, -0.005]), Point([deltaX - 0.002, 2. * aft_span / 3., -0.008]), Point([deltaX - 0.008, aft_span, 0.006]) ]