def __init__(self, front, back): if not isinstance(front, PolyLine2D): front = PolyLine2D(front) if not isinstance(back, PolyLine2D): back = PolyLine2D(back) self.front = front self.back = back
def draw_rib(self, glider): """ Cut trailing edge of outer rib """ outer_rib = self.outer inner_rib = self.inner t_e_allowance = self.config.allowance_trailing_edge p1 = inner_rib[0] + [0, 1] p2 = inner_rib[0] + [0, -1] cuts = outer_rib.cut(p1, p2, extrapolate=True) start = next(cuts)[0] stop = next(cuts)[0] contour = PolyLine2D([]) buerzl = PolyLine2D([ outer_rib[stop], outer_rib[stop] + [t_e_allowance, 0], outer_rib[start] + [t_e_allowance, 0], outer_rib[start] ]) contour += PolyLine2D(outer_rib[start:stop]) contour += buerzl self.plotpart.layers["cuts"] += [contour]
def stack_grid(cls, parts, distance_x, distance_y, draw_grid=True): all_parts = cls() rows = len(parts) columns = len(parts[0]) heights = [0 for _ in range(rows)] widths = [0 for _ in range(columns)] for row_no, row in enumerate(parts): for column_no, part in enumerate(row): widths[column_no] = max(widths[column_no], part.width) heights[row_no] = max(heights[row_no], part.height) y = 0 for row_no, row in enumerate(parts): x = 0 for column_no, part in enumerate(row): if isinstance(part, Layout): drawing = part else: drawing = cls([part]) drawing.move_to([x, y]) all_parts += drawing x += widths[column_no] x += distance_x y += heights[row_no] y += distance_y if draw_grid: grid = PlotPart(material_code="grid") height = all_parts.height width = all_parts.width x = y = 0 for col_width in widths[:-1]: x += col_width x += distance_x / 2 line = PolyLine2D([[x, 0], [x, height]]) grid.layers["grid"].append(line) x += distance_x / 2 for row_height in heights[:-1]: y += row_height y += distance_y / 2 line = PolyLine2D([[0, y], [width, y]]) grid.layers["grid"].append(line) y += distance_y / 2 all_parts.parts.append(grid) return all_parts
def get_half_shape(self): """ Return shape of the glider: [ribs, front, back] """ num = self.num_shape_interpolation front_int = self.front_curve.interpolation(num=num) back_int = self.back_curve.interpolation(num=num) dist = self.rib_x_values front = [[x, front_int(x)] for x in dist] back = [[x, back_int(x)] for x in dist] return Shape(PolyLine2D(front), PolyLine2D(back))
def _get_middle_line(self, x=0.5): line = [] for left, right in zip(*self.ballooned): line.append(left + x * (right - left)) return PolyLine2D(line)
def get_baseline(self, pct): shape = self.get_half_shape() line = [] for i in range(shape.rib_no): line.append(shape.get_point(i, pct)) return PolyLine2D(line)
def test_flat(self): prof = self.rib.profile_2d.copy() prof = PolyLine2D(prof.data) * [self.rib.chord, self.rib.chord] print(self.rib.profile_2d, prof) #prof.scale(self.rib.chord) gib_pos = [n.rib_pos for n in self.attachment_points] gib_pos.sort() hole_pos = [(x1 + x2) / 2 for x1, x2 in zip(gib_pos[:-1], gib_pos[1:])] rigid = RigidFoil(-.15, .12) r_flat = rigid.get_flattened(self.rib) print(self.rib.rotation_matrix, norm(self.rib.rotation_matrix.dot([2, 0, 0]))) Graph.Graphics([ Graph.Line(prof), Graph.Line(self.rib.profile_2d.data * self.rib.chord), Graph.Line(r_flat) ]) Graph.Graphics([ Graph.Line([self.rib.align(p, scale=False) for p in prof.data]), Graph.Line([self.rib.align(p, scale=False) for p in r_flat]), Graph.Line(self.rib.profile_3d.data) ])
def insert_diagonals(self): for cell_no, cell in enumerate(self.glider_3d.cells): for diagonal in cell.diagonals: left = [ abs(p[0]) for p in (diagonal.left_front, diagonal.left_back) ] right = [ abs(p[0]) for p in (diagonal.right_front, diagonal.right_back) ] points_left = [ self.glider_2d.shape.get_shape_point(cell_no, p) for p in left ] points_right = [ self.glider_2d.shape.get_shape_point(cell_no + 1, p) for p in right ] self.drawing.parts.append( PlotPart(marks=[ PolyLine2D(points_left + points_right[::-1] + points_left[:1]) ])) return self
def import_dxf(cls, dxfile): """ Imports groups and blocks from a dxf file :param dxfile: filename :return: """ import ezdxf dxf = ezdxf.readfile(dxfile) dwg = cls() groups = list(dxf.groups) for panel_name, panel in groups: new_panel = PlotPart(name=panel_name) dwg.parts.append(new_panel) for entity in panel: layer = entity.dxf.layer new_panel.layers[layer].append( PolyLine2D([p[:2] for p in entity])) #blocks = list(dxf.blocks) blockrefs = dxf.modelspace().query("INSERT") for blockref in blockrefs: name = blockref.dxf.name block = dxf.blocks.get(name) new_panel = PlotPart(name=block.name) dwg.parts.append(new_panel) for entity in block: layer = entity.dxf.layer try: line = [v.dxf.location[:2] for v in entity] if entity.dxf.flags % 2: line.append(line[0]) new_panel.layers[layer].append(PolyLine2D(line)) except: pass new_panel.rotate(-blockref.dxf.rotation * math.pi / 180) new_panel.move(blockref.dxf.insert[:2]) # block.name #return blocks return dwg
def _normalize(line, target_lengths): new_line = [line[0]] last_node = line[0] segments = line.get_segments() for segment, target_length in zip(segments, target_lengths): scale = target_length / norm(segment) last_node = last_node + scale * segment new_line.append(last_node) return PolyLine2D(new_line)
def _get_inner_outer(self, x_value): ik = get_x_value(self.x_values, x_value) #ik = get_x_value(self.x_values, position) inner = self.inner[ik] outer = inner + PolyLine2D( self.inner).get_normal(ik) * self.config.allowance_general #inner = self.inner[ik] # outer = self.outer[ik] return inner, outer
def insert_cells(self): cells = [] for cell_no in range(self.glider_2d.shape.half_cell_num): p1 = self.glider_2d.shape.get_shape_point(cell_no, 0) p2 = self.glider_2d.shape.get_shape_point(cell_no + 1, 0) p3 = self.glider_2d.shape.get_shape_point(cell_no + 1, 1) p4 = self.glider_2d.shape.get_shape_point(cell_no, 1) cells.append(PolyLine2D([p1, p2, p3, p4, p1])) self.drawing.parts.append( PlotPart(marks=cells, material_code="cell_numbers"))
def get_arc_positions(self, x_values): """ calculate y/z positions vor the arc-curve, given a shape's rib-x-values :param x_values: :return: [p0, p1,...] """ # Symmetric-Bezier-> start from 0.5 arc_curve = PolyLine2D([ self.curve(i) for i in np.linspace(0.5, 1, self.num_interpolation_points) ]) arc_curve_length = arc_curve.get_length() scale_factor = arc_curve_length / x_values[-1] _positions = [arc_curve.extend(0, x * scale_factor) for x in x_values] positions = PolyLine2D([arc_curve[p] for p in _positions]) if not self.has_center_cell(x_values): positions[0][0] = 0 # rescale return positions
def insert_lines(self): self.insert_design() self.insert_attachment_points(True) for line in self.glider_2d.lineset.lines: pp = PlotPart() layer = pp.layers["line_" + line.layer] layer += [ PolyLine2D([ line.lower_node.get_2D(self.glider_2d.shape), line.upper_node.get_2D(self.glider_2d.shape) ]) ] self.drawing.parts.append(pp) return self
def insert_design(self, lower=True): part = PlotPart() for cell_no, cell_panels in enumerate(self.glider_2d.get_panels()): def match(panel): if lower: # -> either on the left or on the right it should go further than 0 return panel.cut_back["left"] > 0 or panel.cut_back[ "right"] > 0 else: # should start before zero at least once return panel.cut_front["left"] < 0 or panel.cut_front[ "right"] < 0 panels = filter(match, cell_panels) for panel in panels: def get_val(val): if lower: return max(val, 0) else: return max(-val, 0) left_front = get_val(panel.cut_front["left"]) rigth_front = get_val(panel.cut_front["right"]) left_back = get_val(panel.cut_back["left"]) right_back = get_val(panel.cut_back["right"]) p1 = self.glider_2d.shape.get_shape_point(cell_no, left_front) p2 = self.glider_2d.shape.get_shape_point(cell_no, left_back) p3 = self.glider_2d.shape.get_shape_point( cell_no + 1, right_back) p4 = self.glider_2d.shape.get_shape_point( cell_no + 1, rigth_front) part.layers[panel.material_code].append( PolyLine2D([p1, p2, p3, p4, p1])) #self.drawing.parts.append(PlotPart( # cuts=[PolyLine2D([p1, p2, p3, p4, p1])], # material_code=panel.material_code)) self.drawing.parts.append(part) return self
def test_show_points(self): nvek = PolyLine2D(self.profile.normvectors) def draw_x(x): ik = self.profile(x) p = self.profile[ik] n = nvek[ik] * 0.02 return openglider.plots.marks.cross(p - n, p + n, rotation=True) x_pos = [-0.9, -.2, .3, .8] nodes = [draw_x(x) for x in x_pos] elems = [openglider.graphics.Line(self.profile.data)] for n in nodes: for l in n: elems.append(openglider.graphics.Line(l)) openglider.graphics.Graphics2D(elems)
def draw_border(self, border=0.1, append=True): if not self.parts: return PlotPart() bbox = self.bbox[:] bbox[0][0] -= border bbox[0][1] -= border bbox[1][0] += border bbox[1][1] -= border bbox[2][0] += border bbox[2][1] += border bbox[3][0] -= border bbox[3][1] += border bbox.append(bbox[0]) data = [PolyLine2D(bbox)] border = PlotPart(drawing_boundary=data) if append: self.parts.append(border) return border
def insert_drib_mark(self, drib, right=False): if right: p1 = drib.right_front p2 = drib.right_back else: p1 = drib.left_front p2 = drib.left_back if p1[1] == p2[1] == -1: self.insert_mark(p1[0], self.config.marks_diagonal_front) self.insert_mark(p2[0], self.config.marks_diagonal_back) self.insert_mark(p1[0], self.config.marks_laser_diagonal, "L0") self.insert_mark(p2[0], self.config.marks_laser_diagonal, "L0") elif p1[1] == p2[1] == 1: self.insert_mark(-p1[0], self.config.marks_diagonal_back) self.insert_mark(-p2[0], self.config.marks_diagonal_front) self.insert_mark(-p1[0], self.config.marks_laser_diagonal, "L0") self.insert_mark(-p2[0], self.config.marks_laser_diagonal, "L0") else: p1 = self.get_point(*p1) p2 = self.get_point(*p2) self.plotpart.layers["marks"].append( PolyLine2D([p1, p2], name=drib.name))
def draw_rib(self, glider): """ Cut trailing edge of outer rib """ outer_rib = self.outer inner_rib = self.inner t_e_allowance = self.config.allowance_trailing_edge p1 = inner_rib[0] + [0, 1] p2 = inner_rib[0] + [0, -1] cuts = outer_rib.cut(p1, p2, extrapolate=True) start = next(cuts)[0] stop = next(cuts)[0] contour = PolyLine2D([]) if isinstance(self.rib, openglider.glider.rib.SingleSkinRib): # outer is going from the back back until the singleskin cut singleskin_cut_left = self._get_singleskin_cut(glider) single_skin_cut = self.rib.profile_2d(singleskin_cut_left) buerzl = PolyLine2D([ inner_rib[0], inner_rib[0] + [t_e_allowance, 0], outer_rib[start] + [t_e_allowance, 0], outer_rib[start] ]) contour += PolyLine2D(outer_rib[start:single_skin_cut]) contour += PolyLine2D(inner_rib[single_skin_cut:stop]) contour += buerzl else: buerzl = PolyLine2D([ outer_rib[stop], outer_rib[stop] + [t_e_allowance, 0], outer_rib[start] + [t_e_allowance, 0], outer_rib[start] ]) contour += PolyLine2D(outer_rib[start:stop]) contour += buerzl self.plotpart.layers["cuts"] += [contour]
def update_shape(self, preview=False): self.parametric_glider.shape.front_curve.controlpoints = list( map(vector2D, self.front_cpc.control_pos)) self.parametric_glider.shape.back_curve.controlpoints = list( map(vector2D, self.back_cpc.control_pos)) self.parametric_glider.shape.rib_dist_controlpoints = list( map(vector2D, self.cell_dist_cpc.control_pos)) self.shape.removeAllChildren() mirrored_sep = coin.SoSeparator() sep = coin.SoSeparator() self.shape += mirrored_sep, sep mirror = coin.SoMatrixTransform() mirror.matrix.setValue(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) mirrored_sep += mirror, sep _shape = self.parametric_glider.shape.get_half_shape() ribs = _shape.ribs front = _shape.front back = _shape.back front[0, 0] = 0 back[0, 0] = 0 dist_line = self.parametric_glider.shape.fast_interpolation sep += (Line(front, width=2).object) sep += (Line(back, width=2).object) # sep += (Line([back.data[0], front.data[0]], width=2).object) sep += (Line([back.data[-1], front.data[-1]], width=2).object) points = list( map(vector3D, self.parametric_glider.shape.front_curve.data)) sep += (Line(points, color='grey').object) points = list( map(vector3D, self.parametric_glider.shape.back_curve.data)) sep += (Line(points, color='grey').object) self.shape += (Line(dist_line, color='red', width=2).object) # draw circles self.circle_front.removeAllChildren() self.circle_back.removeAllChildren() circle_front = CirclePart( *self.parametric_glider.shape.front_curve.get_sequence(3)) circle_back = CirclePart( *self.parametric_glider.shape.back_curve.get_sequence(3)) self.circle_front.addChild( Line(circle_front.get_sequence(), color="red").object) self.circle_back.addChild( Line(circle_back.get_sequence(), color="red").object) # draw center line self.center_line.removeAllChildren() center_line = [] for rib_no in range(_shape.rib_no): center_line.append(_shape.get_point(rib_no, 0.5)) self.center_line.addChild(Line(center_line, color="red").object) y = _shape.get_point(0, 0.5)[1] x = _shape.get_point(_shape.rib_no - 1, 0)[0] * 1.2 center_line2 = PolyLine2D([[-x, y], [x, y]]) self.center_line.addChild(Line(center_line2, color="red").object) if not preview: for rib in ribs: width = 1 col = 'grey' if list(rib) in (ribs[0], ribs[-1]): width = 2 col = 'black' sep += Line(rib, color=col, width=width).object for i in dist_line: sep += Line([[0, i[1]], i, [i[0], 0]], color='grey').object
def symmetric_fit(polyline, numpoints=numpoints): mirrored = PolyLine2D(polyline[1:]).mirror([0, 0], [0, 1]) symmetric = mirrored[::-1].join(polyline[int(glider.has_center_cell):]) return SymmetricBezier.fit(symmetric, numpoints=numpoints)
def flatten(self, attachment_points): plotpart = PlotPart(material_code=self.panel.material_code, name=self.panel.name) cut_allowances = { "folded": self.config.allowance_entry_open, "parallel": self.config.allowance_trailing_edge, "orthogonal": self.config.allowance_design, "singleskin": self.config.allowance_entry_open, "cut_3d": self.config.allowance_design } cut_types = { "folded": self.config.cut_entry, "parallel": self.config.cut_trailing_edge, "orthogonal": self.config.cut_design, "singleskin": self.config.cut_entry, "cut_3d": self.config.cut_3d } ik_values = self.panel._get_ik_values(self.cell, self.config.midribs) front_left = ik_values[0][0] front_right = ik_values[-1][0] back_left = ik_values[0][1] back_right = ik_values[-1][1] # allowance fallbacks allowance_front = cut_allowances[self.panel.cut_front["type"]] allowance_back = cut_allowances[self.panel.cut_back["type"]] # get allowance from self.panel amount_front = -self.panel.cut_front.get("amount", allowance_front) amount_back = self.panel.cut_back.get("amount", allowance_back) # cuts -> cut-line, index left, index right cut_front = cut_types[self.panel.cut_front["type"]](amount_front) cut_back = cut_types[self.panel.cut_back["type"]](amount_back) inner_front = [(line, ik[0]) for line, ik in zip(self.inner, ik_values)] inner_back = [(line, ik[1]) for line, ik in zip(self.inner, ik_values)] shape_3d_amount_front = [-x for x in self.panel.cut_front["amount_3d"]] shape_3d_amount_back = self.panel.cut_back["amount_3d"] # calculate difference rib->panel for j in (0, -1): # left, right profile = [self.cell.prof1, self.cell.prof2][j] line_2d = self.inner[j][ik_values[j][0]:ik_values[j][-1]] line_3d = profile[ik_values[j][0]:ik_values[j][-1]] diff = line_3d.get_length() - line_2d.get_length() shape_3d_amount_front[j] = -diff / 2 shape_3d_amount_back[j] = diff / 2 if diff > 0.003 or self.panel.name in ("c16p1", "c17p1"): print(self.panel.name, j, diff, line_2d.get_length(), line_3d.get_length()) if self.panel.cut_front["type"] != "cut_3d": dist = np.linspace(shape_3d_amount_front[0], shape_3d_amount_front[-1], len(shape_3d_amount_front)) shape_3d_amount_front = list(dist) if self.panel.cut_back["type"] != "cut_3d": dist = np.linspace(shape_3d_amount_back[0], shape_3d_amount_back[-1], len(shape_3d_amount_back)) shape_3d_amount_back = list(dist) cut_front_result = cut_front.apply(inner_front, self.outer[0], self.outer[1], shape_3d_amount_front) cut_back_result = cut_back.apply(inner_back, self.outer[0], self.outer[1], shape_3d_amount_back) panel_left = self.outer[0][cut_front_result.index_left:cut_back_result. index_left] panel_back = cut_back_result.curve.copy() panel_right = self.outer[1][cut_front_result. index_right:cut_back_result.index_right:-1] panel_front = cut_front_result.curve.copy() # spitzer schnitt # rechts if cut_front_result.index_right >= cut_back_result.index_right: panel_right = PolyLine2D([]) _cuts = panel_front.cut_with_polyline(panel_back, startpoint=len(panel_front) - 1) try: ik_front, ik_back = next(_cuts) panel_back = panel_back[:ik_back] panel_front = panel_front[:ik_front] except StopIteration: pass # todo: fix!! # lechts if cut_front_result.index_left >= cut_back_result.index_left: panel_left = PolyLine2D([]) _cuts = panel_front.cut_with_polyline(panel_back, startpoint=0) try: ik_front, ik_back = next(_cuts) panel_back = panel_back[ik_back:] panel_front = panel_front[ik_front:] except StopIteration: pass # todo: fix aswell! panel_back = panel_back[::-1] if panel_right: panel_right = panel_right[::-1] #print(panel_left) envelope = panel_right + panel_back if len(panel_left) > 0: envelope += panel_left[::-1] envelope += panel_front envelope += PolyLine2D([envelope[0]]) plotpart.layers["envelope"].append(envelope) if self.config.debug: line1, line2 = self._flattened_cell["debug"] plotpart.layers["debug"].append( line1[ik_values[0][0]:ik_values[0][1]]) plotpart.layers["debug"].append( line2[ik_values[-1][0]:ik_values[-1][1]]) # sewings plotpart.layers["stitches"] += [ self.inner[0][cut_front_result.inner_indices[0]:cut_back_result. inner_indices[0]], self.inner[-1][cut_front_result.inner_indices[-1]:cut_back_result. inner_indices[-1]] ] # folding line plotpart.layers["marks"] += [ PolyLine2D([ line[x] for line, x in zip(self.inner, cut_front_result.inner_indices) ]), PolyLine2D([ line[x] for line, x in zip(self.inner, cut_back_result.inner_indices) ]) ] # TODO if False: if panel_right: right = PolyLine2D([ panel_front.last() ]) + panel_right + PolyLine2D([panel_back[0]]) plotpart.layers["cuts"].append(right) plotpart.layers["cuts"].append(panel_back) if panel_left: left = PolyLine2D([ panel_back.last() ]) + panel_left + PolyLine2D([panel_front[0]]) plotpart.layers["cuts"].append(left) plotpart.layers["cuts"].append(panel_front) else: plotpart.layers["cuts"].append(envelope.copy()) self._insert_text(plotpart) self._insert_controlpoints(plotpart) self._insert_attachment_points(plotpart, attachment_points=attachment_points) self._insert_diagonals(plotpart) # self._insert_center_rods(plotpart) # TODO: add in parametric way self._align_upright(plotpart) return plotpart
def _insert_center_rods(self, plotpart): start = -0.15 end = 0.15 front = (self.panel.cut_front["left"] + self.panel.cut_front["right"]) / 2 back = (self.panel.cut_back["left"] + self.panel.cut_back["right"]) / 2 if end < min(self.panel.cut_front["left"], self.panel.cut_front["right"]): return elif start > max(self.panel.cut_back["left"], self.panel.cut_back["right"]): return k_start = get_x_value(self.x_values, start) k_end = get_x_value(self.x_values, end) middle_line = self._get_middle_line(0.5) curve_left = self.ballooned[0] curve_right = self.ballooned[1] # cut with front and back front_left = curve_left[get_x_value(self.x_values, self.panel.cut_front["left"])] front_right = curve_right[get_x_value(self.x_values, self.panel.cut_front["right"])] back_left = curve_left[get_x_value(self.x_values, self.panel.cut_back["left"])] back_right = curve_right[get_x_value(self.x_values, self.panel.cut_back["right"])] cut_fronts = middle_line.cut(front_left, front_right, startpoint=k_start, extrapolate=True) cut_backs = middle_line.cut(back_left, back_right, startpoint=k_end, extrapolate=True) cut_front = next(cut_fronts)[0] cut_back = next(cut_backs)[0] k_front = max(k_start, cut_front) k_back = min(k_end, cut_back) #print(cut_front, k_front, cut_back, k_back, self.panel.cut_front, self.panel.cut_back) if k_back > k_front: plotpart.layers["marks"] += [middle_line[k_front:k_back]] if front < start < back: k_start = get_x_value(self.x_values, start) plotpart.layers["L0"].append(PolyLine2D([middle_line[k_start] ])) if front < end < back: k_end = get_x_value(self.x_values, end) plotpart.layers["L0"].append(PolyLine2D([middle_line[k_end]]))
def _flatten(self, attachment_points, num_folds): plotpart = PlotPart(material_code=self.drib.material_code, name=self.drib.name) left, right = self._get_inner() left_out, right_out = self._get_outer() if num_folds > 0: alw2 = self.config.drib_allowance_folds cut_front = self.config.cut_diagonal_fold(-alw2, num_folds=num_folds) cut_back = self.config.cut_diagonal_fold(alw2, num_folds=num_folds) cut_front_result = cut_front.apply([[left, 0], [right, 0]], left_out, right_out) cut_back_result = cut_back.apply( [[left, len(left) - 1], [right, len(right) - 1]], left_out, right_out) plotpart.layers["cuts"] += [ left_out[cut_front_result.index_left:cut_back_result. index_left] + cut_back_result.curve + right_out[cut_front_result.index_right:cut_back_result. index_right:-1] + cut_front_result.curve[::-1] ] else: p1 = next( left_out.cut(left[0], right[0], startpoint=0, extrapolate=True))[0] p2 = next( left_out.cut(left[len(left) - 1], right[len(right) - 1], startpoint=len(left_out), extrapolate=True))[0] p3 = next( right_out.cut(left[0], right[0], startpoint=0, extrapolate=True))[0] p4 = next( right_out.cut(left[len(left) - 1], right[len(right) - 1], startpoint=len(right_out), extrapolate=True))[0] outer = left_out[p1:p2] outer += right_out[p3:p4][::-1] outer += PolyLine2D([left_out[p1]]) plotpart.layers["cuts"].append(outer) # print("left", left_out[cut_front[1]:cut_back[1]].get_length()) plotpart.layers["marks"].append(PolyLine2D([left[0], right[0]])) plotpart.layers["marks"].append( PolyLine2D([left[len(left) - 1], right[len(right) - 1]])) # print(left, right) plotpart.layers["stitches"] += [left, right] self._insert_attachment_points(plotpart, attachment_points) self._insert_text(plotpart) return plotpart
def get_flattened_cell(self, midribs=10): left, right = openglider.vector.projection.flatten_list( self.prof1, self.prof2) left_bal = left.copy() right_bal = right.copy() ballooning = [ self.ballooning[x] for x in self.rib1.profile_2d.x_values ] for i in range(len(left)): diff = (right[i] - left[i]) * ballooning[i] / 2 left_bal.data[i] -= diff right_bal.data[i] += diff def _normalize(line, target_lengths): new_line = [line[0]] last_node = line[0] segments = line.get_segments() for segment, target_length in zip(segments, target_lengths): scale = target_length / norm(segment) last_node = last_node + scale * segment new_line.append(last_node) return PolyLine2D(new_line) # left_bal_2 = _normalize(left_bal, left.get_segment_lengthes()) right_bal_2 = _normalize(right_bal, right.get_segment_lengthes()) right_bal_3 = right_bal_2.copy() left_bal_3 = left_bal_2.copy() debug_lines = [] debug_lines2 = [] for i in range(len(left_bal)): diff = left_bal_2[i] - right_bal_2[i] dist_new = norm(diff) dist_orig = norm(left_bal[i] - right_bal[i]) diff_per_side = normalize(diff) * ((dist_new - dist_orig) / 2) right_bal_2[i] += diff_per_side left_bal_2[i] -= diff_per_side debug_lines.append(PolyLine2D([left_bal_2[i], right_bal_2[i]])) debug_lines2.append(PolyLine2D([left_bal[i], right_bal[i]])) inner = [] for x in openglider.utils.linspace(0, 1, 2 + midribs): l1 = left_bal * (1 - x) l2 = right_bal * x inner.append(l1.add(l2)) #ballooned = [left_bal, right_bal] return { "inner": inner, "ballooned": [left_bal, right_bal], "ballooned_new": [left_bal_2, right_bal_2], "ballooned_new_copy": [left_bal_3, right_bal_3], "debug": [left, right], "debug_1": debug_lines, "debug_2": debug_lines2 }