def add_simple_hole_from_offset(self, thickness): """ :param float or int thickness: wall_thickenss in mm :return: """ logger = logging.getLogger(__name__) # path = prim.Path(prim.GeometricFunctions.offset_curve(self.get_path(), thickness, dir=1, divisions=1)) path = copy.deepcopy(self.get_path()) path = prim.GeometricFunctions.clean_intersections( prim.GeometricFunctions.parallel_curve(path, thickness, 1, False), path, thickness) self.holes = [CrossSection(prim.Path(path))]
def slice_into_cross_sections(self, origin_plane, spacing, length): """ :param Plane origin_plane: :param float spacing: :return: """ self.trimesh_cross_sections = list() heights = list() for i in range(length): heights.append(spacing * i) origin = np.array(origin_plane.origin) normal = np.array(origin_plane.normal) sections = self.mesh.section_multiplane(plane_origin=origin, plane_normal=normal, heights=heights) if sections is not None: self.trimesh_cross_sections.extend(sections) self.cross_sections = list() for section in sections: points = list() for ind in range(0, len(section.discrete[0])): points.append( prim.Point(section.discrete[0][ind][0], section.discrete[0][ind][1], 0)) path = prim.GeometricFunctions.normalize_path_points( PointManip.reorder_2d_cw(points, method=1), 516) self.cross_sections.append( CrossSection(section_list=[prim.Path(path)])) self.logger.debug('section: %s', self.cross_sections[-1]) self.center_cross_sections() self.close_sections() else: raise AttributeError( 'Error: Plane with origin(%s) does not intersect the STL' % origin_plane.origin)
def close_sections(self): for ind in range(0, len(self.cross_sections)): self.cross_sections[ind] = CrossSection( prim.Path( prim.GeometricFunctions.close_path( self.cross_sections[ind].get_path())))
def create_cut_path_from_wing(wing, wire_cutter, debug_kerf=False): """ :param WingSegment wing: :param WireCutter wire_cutter: :return: """ logger = logging.getLogger(__name__) if not wing.prepped: raise ValueError('Error: Wing has not been prepped for slicing') cut_path = CutPath([], []) root_foil = copy.deepcopy(wing.root_airfoil) tip_foil = copy.deepcopy(wing.tip_airfoil) if wire_cutter.kerf is not None: if wing.root_chord > wing.tip_chord: kerf_root = wire_cutter.kerf kerf_tip = wire_cutter.kerf * wing.root_chord / wing.tip_chord else: kerf_root = wire_cutter.kerf * wing.root_chord / wing.tip_chord kerf_tip = wire_cutter.kerf if debug_kerf: prim.GeometricFunctions.plot_path(root_foil, 1) prim.GeometricFunctions.plot_path(tip_foil, 2) root_foil = prim.GeometricFunctions.offset_curve(root_foil, kerf_root, dir=0, divisions=2) tip_foil = prim.GeometricFunctions.offset_curve(tip_foil, kerf_tip, dir=0, divisions=2) leading_edge_root = prim.GeometricFunctions.get_point_from_min_coord( root_foil, 'x') leading_edge_tip = prim.GeometricFunctions.get_point_from_min_coord( tip_foil, 'x') offset = leading_edge_root['x'] if leading_edge_root[ 'x'] < leading_edge_tip['x'] else leading_edge_tip['x'] if offset < 0: PointManip.Transform.translate(root_foil, [-offset, 0, 0]) PointManip.Transform.translate(tip_foil, [-offset, 0, 0]) if debug_kerf: prim.GeometricFunctions.plot_path(root_foil, 3) prim.GeometricFunctions.plot_path(tip_foil, 4) plt.legend([ 'Root Foil', 'Tip Foil', 'Root Foil with %smm kerf' % kerf_root, 'Tip Foil with %smm kerf' % kerf_tip ]) plt.axis('equal') plt.show() root_z = root_foil[0]['z'] tip_z = tip_foil[0]['z'] logger.debug('Root: %s | Tip: %s' % (root_foil[0], tip_foil[0])) start_point1 = prim.Point(0, 0, root_z) start_point2 = prim.Point(0, 0, tip_z) next_point1 = start_point1 + prim.Point(0, wire_cutter.start_height, 0) next_point2 = start_point2 + prim.Point(0, wire_cutter.start_height, 0) logger.debug('sp1: %s | sp2: %s | np1: %s | np2: %s' % (start_point1, start_point2, next_point1, next_point2)) seg_link1 = prim.SectionLink(start_point1, next_point1, fast_cut=True) seg_link2 = prim.SectionLink(start_point2, next_point2, fast_cut=True) cut_path.add_segment_to_cut_lists(segment_1=seg_link1, segment_2=seg_link2) start_point1 = next_point1 start_point2 = next_point2 next_point1 = start_point1 + prim.Point(wire_cutter.start_depth, 0, 0) # The start depth of the second axis needs to be offset by the difference between the two foils positioning, # this is to account for sweep in the wing next_point2 = start_point2 + prim.Point( wire_cutter.start_depth - (root_foil[0]['x'] - tip_foil[0]['x']), 0, 0) logger.debug('sp1: %s | sp2: %s | np1: %s | np2: %s' % (start_point1, start_point2, next_point1, next_point2)) test_line = prim.Line.line_from_points(next_point1, next_point2) p1 = test_line.get_extrapolated_point(0, constraint_dim='z') p2 = test_line.get_extrapolated_point(wire_cutter.wire_length, constraint_dim='z') if p1['x'] < wire_cutter.start_depth or p2[ 'x'] < wire_cutter.start_depth: offset = max(wire_cutter.start_depth - p1['x'], wire_cutter.start_depth - p2['x']) next_point1 += prim.Point(offset, 0, 0) next_point2 += prim.Point(offset, 0, 0) # Translate both airfoils by the same offset to keep them inline logger.debug('Next Point X: %s', next_point1['x']) PointManip.Transform.translate(root_foil, [next_point1['x'], next_point1['y'], 0]) PointManip.Transform.translate(tip_foil, [next_point1['x'], next_point1['y'], 0]) logger.debug('Root Airfoil Leading Edge: %s', root_foil[0]) next_point1 += root_foil[0] - next_point1 logger.debug('Next Point X after offset: %s', next_point1['x']) next_point2 += tip_foil[0] - next_point2 logger.debug('Root Airfoil Leading Edge: %s', root_foil[0]) seg_link1 = prim.SectionLink(start_point1, next_point1, fast_cut=False) seg_link2 = prim.SectionLink(start_point2, next_point2, fast_cut=False) cut_path.add_segment_to_cut_lists(segment_1=seg_link1, segment_2=seg_link2) root_ind_split = prim.GeometricFunctions.get_index_max_coord( root_foil, 'x') tip_ind_split = prim.GeometricFunctions.get_index_max_coord( tip_foil, 'x') top_root = root_foil[0:root_ind_split + 1] bottom_root = [root_foil[0]] bottom_root.extend( sorted(root_foil[root_ind_split:-1], key=lambda point: point['x'])) top_tip = tip_foil[0:tip_ind_split + 1] bottom_tip = [tip_foil[0]] bottom_tip.extend( sorted(tip_foil[tip_ind_split:-1], key=lambda point: point['x'])) cut_path.add_segment_to_cut_lists(CrossSection(prim.Path(top_root)), CrossSection(prim.Path(top_tip))) start_point1 = top_root[-1] start_point2 = top_tip[-1] logger.debug('TE of Top Root: %s | TE of Top Tip: %s' % (start_point1, start_point2)) next_point1, next_point2 = CutPath._add_loopback( cut_path, wire_cutter, root_z, tip_z) start_point1 = next_point1 start_point2 = next_point2 next_point1 = start_point1 + prim.Point(wire_cutter.start_depth, 0, 0) next_point2 = start_point2 + prim.Point( wire_cutter.start_depth - (root_foil[0]['x'] - tip_foil[0]['x']), 0, 0) logger.debug('sp1: %s | sp2: %s | np1: %s | np2: %s' % (start_point1, start_point2, next_point1, next_point2)) test_line = prim.Line.line_from_points(next_point1, next_point2) p1 = test_line.get_extrapolated_point(0, constraint_dim='z') p2 = test_line.get_extrapolated_point(wire_cutter.wire_length, constraint_dim='z') if p1['x'] < wire_cutter.start_depth or p2[ 'x'] < wire_cutter.start_depth: offset = max(wire_cutter.start_depth - p1['x'], wire_cutter.start_depth - p2['x']) next_point1 += prim.Point(offset, 0, 0) next_point2 += prim.Point(offset, 0, 0) next_point1 += root_foil[0] - next_point1 logger.debug('Next Point X after offset: %s', next_point1['x']) next_point2 += tip_foil[0] - next_point2 logger.debug('Root Airfoil Leading Edge: %s', root_foil[0]) seg_link1 = prim.SectionLink(start_point1, next_point1, fast_cut=False) seg_link2 = prim.SectionLink(start_point2, next_point2, fast_cut=False) cut_path.add_segment_to_cut_lists(segment_1=seg_link1, segment_2=seg_link2) cut_path.add_segment_to_cut_lists(CrossSection(prim.Path(bottom_root)), CrossSection(prim.Path(bottom_tip))) CutPath._add_loopback(cut_path, wire_cutter, root_z, tip_z) return cut_path
def subdivide(self, num_sections): """ :param int num_sections: :return: """ ret_val = list() if num_sections < 2: ret_val = [self] else: center = prim.Point(0, 0, 0) points1, points2 = self.get_path() start_point1 = points1[0] start_point2 = points2[0] for point in points1: center += point center /= len(points1) hole1, hole2 = self.section1.get_path_hole( ), self.section2.get_path_hole() if hole1 is not None: start_point1_hole = hole1[0] start_point2_hole = hole2[0] else: start_point1_hole = None start_point2_hole = None for index in range(num_sections): curr_section1 = list() curr_section2 = list() arc_len = 360 / num_sections upper_range = arc_len * (index + 1) lower_range = arc_len * index for point in points1: theta = (np.rad2deg( np.arctan2(point['y'] - center['y'], point['x'] - center['x'])) + 180) % 360 if lower_range < theta <= upper_range: curr_section1.append(point) if hole1 is not None: tmp_list = list() for point in hole1: theta = (np.rad2deg( np.arctan2(point['y'] - center['y'], point['x'] - center['x'])) + 180) % 360 if lower_range < theta <= upper_range: tmp_list.append(point) for point in reversed(tmp_list): curr_section1.append(point) else: curr_section1.append(prim.Point(0, 0, 0)) for point in points2: theta = (np.rad2deg( np.arctan2(point['y'] - center['y'], point['x'] - center['x'])) + 180) % 360 if lower_range < theta <= upper_range: curr_section2.append(point) if hole2 is not None: tmp_list = list() for point in hole2: theta = (np.rad2deg( np.arctan2(point['y'] - center['y'], point['x'] - center['x'])) + 180) % 360 if lower_range < theta <= upper_range: tmp_list.append(point) for point in reversed(tmp_list): curr_section2.append(point) else: curr_section2.append(prim.Point(0, 0, 0)) if start_point1 in curr_section1: path1 = prim.GeometricFunctions.close_path( PointManip.reorder_2d_cw(curr_section1, method=2)) path2 = prim.GeometricFunctions.close_path( PointManip.reorder_2d_cw(curr_section2, method=2)) else: path1 = prim.GeometricFunctions.close_path(curr_section1) path2 = prim.GeometricFunctions.close_path(curr_section2) ret_val.append( CrossSectionPair(section1=CrossSection(prim.Path(path1)), section2=CrossSection(prim.Path(path2)))) return ret_val