def test_export_with_keep_unresolved_part_containing_primitive(self): document = App.newDocument() box = document.addObject('Part::Box', 'Box') box.Label = 'Cube' box.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) part = document.addObject('App::Part', 'Part') part.Label = 'Part' part.addObject(box) part.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) document.recompute() obj_filename = 'translated_part_containing_cube.obj' with open(os.path.join(os.path.dirname(__file__), obj_filename)) as f: expected = f.read() def keep_unresolved(obj: object, path: List[object]) -> bool: return obj.Name == 'Part' obj_file_contents = freecad_to_obj.export( [part], keep_unresolved=keep_unresolved) self.assertEqual(obj_file_contents, expected)
def test_export_with_keep_unresolved_transform_link_to_primitive(self): document = App.newDocument() box = document.addObject('Part::Box', 'Box') box.Label = 'Cube' box.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) link = document.addObject('App::Link', 'Link') link.Label = 'CubeLink' link.setLink(box) link.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) link.LinkTransform = True document.recompute() obj_filename = 'link_to_translated_cube.obj' with open(os.path.join(os.path.dirname(__file__), obj_filename)) as f: expected = f.read() def keep_unresolved(obj: object, path: List[object]) -> bool: return obj.Label == 'CubeLink' obj_file_contents = freecad_to_obj.export( [link], keep_unresolved=keep_unresolved) self.assertEqual(obj_file_contents, expected)
def _rotate_points(plist, axisdegree): """Return a list of points rotated around the origin The rotation is defined by three angles in degrees and the rotation order is z, y, x, each around the newly rotated axis. Parameters ---------- - plist: list of Vector. - axisdegree: Vector with angles in deg. """ newlist = [] for v in plist: if axisdegree.z != 0: rota = Rotation(Vector(0, 0, 1), axisdegree.z) v = rota.multVec(v) if axisdegree.y != 0: rota = Rotation(Vector(0, 1, 0), axisdegree.y) v = rota.multVec(v) if axisdegree.x != 0: rota = Rotation(Vector(1, 0, 0), axisdegree.x) v = rota.multVec(v) newlist.append(v) return newlist
def test_export_with_sphere_link_transform_true(self): test_package_path = Path(__file__).parent sphere_document = App.newDocument('Sphere') sphere = sphere_document.addObject('Part::Sphere', 'Sphere') sphere.Label = 'Sphere' sphere.Placement = Placement(Vector(10, 0, 0), Rotation(Vector(0, 0, 1), 0)) sphere_document.recompute() sphere_document_path = test_package_path.joinpath('Sphere.FCStd') sphere_document.saveAs(str(sphere_document_path)) link_document = App.newDocument('Link') link_document_path = test_package_path.joinpath('Link.FCStd') link_document.saveAs(str(link_document_path)) link = link_document.addObject('App::Link', 'Link') link.setLink(sphere) link.Label = sphere.Label link.LinkTransform = True link_document.recompute() with open( os.path.join(os.path.dirname(__file__), 'translated_sphere.obj')) as f: expected = f.read() obj_file_contents = freecad_to_obj.export([link]) self.assertEqual(obj_file_contents, expected) sphere_document_path.unlink() link_document_path.unlink()
def test_export_with_link_to_translated_primitive(self): test_package_path = Path(__file__).parent cube_document = App.newDocument('Cube') box = cube_document.addObject('Part::Box', 'Box') box.Label = 'Cube' box.Placement = Placement(Vector(10, 0, 0), Rotation(Vector(0, 0, 1), 0)) cube_document_path = test_package_path.joinpath('Cube.FCStd') cube_document.saveAs(str(cube_document_path)) link_document = App.newDocument('CubeLink') link_document_path = test_package_path.joinpath('LinkCube.FCStd') link_document.saveAs(str(link_document_path)) link = link_document.addObject('App::Link', 'Link') link.setLink(box) link.Label = box.Label link.LinkTransform = False link_document.recompute() with open(os.path.join(os.path.dirname(__file__), 'cube.obj')) as f: expected = f.read() obj_file_contents = freecad_to_obj.export([link]) self.assertEqual(obj_file_contents, expected) cube_document_path.unlink() link_document_path.unlink()
def move_parts( parts: List[Part.Shape], placement: Placement, origin_translation_offset: Vector, reference_dimensions: List[float], rotation: Rotation = Rotation()) -> None: """Move parts based on placement, origin translation offset, reference dimensions, and optionally a rotation. :param parts: List of parts to move. :type parts: List[Part.Shape] :param placement: A placement to apply to the given parts. :type placement: Placement :param origin_translation_offset: Offset the parts to the origin. :type origin_translation_offset: Vector :param reference_dimensions: Reference dimensions :type reference_dimensions: Vector :param rotation: Rotation, defaults to Rotation() :type rotation: Rotation, optional """ translation_offset = _get_translation_offset(reference_dimensions, rotation, origin_translation_offset) for part in parts: part.translate(translation_offset) placement_rotation = placement.Rotation part.rotate(translation_offset, placement_rotation.Axis, degrees(placement_rotation.Angle)) part.translate(placement.Base)
def test_get_axis_frame_attachment_kwargs_for_right_face(self): right_faces = self.frame.Proxy.get_faces_for_side(Side.RIGHT) for right_face in right_faces: result = get_axis_frame_attachment_kwargs(self.frame, right_face, CoordinateAxis.Y) frame_size = self.frame.Size.Value three_inches = 76.2 # in millimeters (mm) length = frame_size + three_inches expected = { 'origin_translation_offset': Vector(0.0, 0.0, -1.0), 'placement': Placement( Vector( frame_size + AngleFrameConnector.axis_side_mount_width, -21.14446, # TODO: Replace magic number with something meaningful 305.2 # TODO: Replace magic number with something meaningful ), Rotation(), Vector()), 'length_value': length, 'orientation': CoordinateAxis.Y, 'side': Side.RIGHT } self.assert_result_and_expected_are_equal(result, expected)
def _render_pins(self, label, base_plane, backwards, count): Console.PrintMessage("_render_pins({},{},{})\n".format( label, backwards, count)) pin_base_datum_point = self.brick.newObject( 'PartDesign::Point', 'pin_base_{}_datum_point'.format(label)) pin_base_datum_point.Support = [(base_plane, '')] pin_base_datum_point.MapMode = 'ObjectOrigin' pin_base_datum_point.ViewObject.Visibility = False if self.pins_offset: pin_base_datum_point.AttachmentOffset = Placement( Vector(DIMS_STUD_SPACING / 2, DIMS_TECHNIC_HOLE_CENTRE_HEIGHT, 0), Rotation(0, 0, 0)) else: pin_base_datum_point.AttachmentOffset = Placement( Vector(0, DIMS_TECHNIC_HOLE_CENTRE_HEIGHT, 0), Rotation(0, 0, 0)) pin_tip_offset = DIMS_PIN_LENGTH if backwards: pin_tip_offset *= -1 pin_tip_datum_point = self.brick.newObject( 'PartDesign::Point', 'pin_tip_{}_datum_point'.format(label)) pin_tip_datum_point.Support = [(base_plane, '')] pin_tip_datum_point.MapMode = 'ObjectOrigin' pin_tip_datum_point.ViewObject.Visibility = False if self.pins_offset: pin_tip_datum_point.AttachmentOffset = Placement( Vector(DIMS_STUD_SPACING / 2, DIMS_TECHNIC_HOLE_CENTRE_HEIGHT, pin_tip_offset), Rotation(0, 0, 0)) else: pin_tip_datum_point.AttachmentOffset = Placement( Vector(0, DIMS_TECHNIC_HOLE_CENTRE_HEIGHT, pin_tip_offset), Rotation(0, 0, 0)) pin_datum_line = self.brick.newObject( 'PartDesign::Line', 'pin_{}_datum_line'.format(label)) pin_datum_line.Support = [(pin_base_datum_point, ''), (pin_tip_datum_point, '')] pin_datum_line.MapMode = 'TwoPointLine' pin_datum_line.ViewObject.Visibility = False pin_features = render_pin(label, pin_datum_line, self.brick, self.doc) if count > 1: self._render_linear_pattern(label, pin_features, count)
def create_window(obj_name, document): """Create a window.""" obj = document.addObject('Part::Feature', obj_name) obj.Shape = Part.makeBox(5, 4, 5) # Center window to wall obj.Placement = Placement(Vector(2.5, -1, 2.5), Rotation()) return obj
def make_outline(self, fp): self.updating = True if fp.Method == 'normal': outline = fp.Part.Shape.makeOffsetShape(fp.BeamWidth / 2, 1e-7) elif fp.Method == '2D': outline = fp.Part.Shape.makeOffset2D(fp.BeamWidth / 2) fp.Normal = self.getNormal(fp.Part) elif fp.Method == '3D': outline = fp.Part.Shape.makeOffsetShape(fp.BeamWidth / 2, 1e-7) fp.Normal = self.getNormal(fp.Part) else: face = self.get_biggest_face(fp.Part) if face: outline = face.makeOffset2D(fp.BeamWidth / 2) fp.Normal = face.normalAt(0, 0) elif fp.Method == 'auto': try: outline = fp.Part.Shape.makeOffset2D(fp.BeamWidth / 2) except Exception as ex: outline = fp.Part.Shape.makeOffsetShape(fp.BeamWidth / 2, 1e-7) fp.Normal = self.getNormal(fp.Part) fp.Shape = Part.Compound(outline.Wires); fp.Label = fp.Part.Label + ' offset' fp.Placement = outline.Placement if fp.Placement.Rotation.Axis.z < 0: fp.Placement.Rotation.Axis = fp.Placement.Rotation.Axis * -1 if fp.Method != 'normal': if fp.Normal.z < 0: fp.Normal = fp.Normal * -1 rotation_to_apply = Rotation(fp.Normal, Vector(0, 0, 1)) new_rotation = rotation_to_apply.multiply(fp.Placement.Rotation) fp.Placement.Rotation = new_rotation self.rotate_biggest_side_up(fp) self.updating = False
def shapeAnalyse(self, name, shape): ## Create a new object with the shape of the current arch object ## His placment is set to 0,0,0 obj = FreeCAD.ActiveDocument.addObject('Part::Feature', name) obj.Shape = shape obj.Placement.Base = FreeCAD.Vector(0.0, 0.0, 0.0) obj.Placement.Rotation = FreeCAD.Rotation( FreeCAD.Vector(0.0, 0.0, 1.0), 0.0) FreeCAD.ActiveDocument.recompute() ## Get the face to align with XY plane faces = obj.Shape.Faces facesMax = self.getFacesMax(faces) coupleEquerre = self.getCoupleFacesEquerre(facesMax) ## Get the normal of this face nv1 = coupleEquerre[0][0].normalAt(0, 0) ## Get the goal normal vector zv = Vector(0, 0, 1) ## Find and apply a rotation to the object to align face pla = obj.Placement rot = pla.Rotation rot1 = Rotation(nv1, zv) newrot = rot.multiply(rot1) pla.Rotation = newrot ## Get the face to align with XY plane faces = obj.Shape.Faces facesMax = self.getFacesMax(faces) coupleEquerre = self.getCoupleFacesEquerre(facesMax) ## Get the longest edge from aligned face maxLength = 0. for e in coupleEquerre[0][0].Edges: if e.Length > maxLength: maxLength = e.Length edgeMax = e ## Get the angle between edge and X axis and rotate object vec = DraftGeomUtils.vec(edgeMax) vecZ = FreeCAD.Vector(vec[0], vec[1], 0.0) pos2 = obj.Placement.Base rotZ = math.degrees( DraftVecUtils.angle(vecZ, FreeCAD.Vector(1.0, 0.0, 0.0), zv)) Draft.rotate([obj], rotZ, pos2, axis=zv, copy=False) bb = obj.Shape.BoundBox movex = bb.XMin * -1 movey = bb.YMin * -1 movez = bb.ZMin * -1 Draft.move([obj], FreeCAD.Vector(movex, movey, movez)) FreeCAD.ActiveDocument.recompute() ## Get the boundbox analyse = [ obj.Shape.BoundBox.YLength, obj.Shape.BoundBox.ZLength, obj.Shape.BoundBox.XLength ] if not "Shape" in self.export: FreeCAD.ActiveDocument.removeObject(name) return analyse
def rotate_biggest_side_up(self, fp): bbox = fp.Shape.optimalBoundingBox() xmin = bbox.XLength angle = 0.0 r = fp.Placement.Rotation r_best = r step = 180 / 16 while angle + step < 180: angle = angle + step rotation_to_apply = Rotation() rotation_to_apply.Axis = Vector(0, 0, 1) rotation_to_apply.Angle = math.radians(angle) fp.Placement.Rotation = rotation_to_apply.multiply(r) bbox = fp.Shape.optimalBoundingBox() if xmin > bbox.XLength: xmin = bbox.XLength r_best = fp.Placement.Rotation fp.Placement.Rotation = r_best
def test_export_with_translated_part_containing_translated_primitive(self): document = App.newDocument() box = document.addObject('Part::Box', 'Box') box.Label = 'Cube' box.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) part = document.addObject('App::Part', 'Part') part.addObject(box) part.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) document.recompute() with open( os.path.join(os.path.dirname(__file__), 'translated_cube.obj')) as f: expected = f.read() obj_file_contents = freecad_to_obj.export([part]) self.assertEqual(obj_file_contents, expected)
def rotatePoints(plist, axisdegree): newlist = [] for v in plist: if axisdegree.z != 0: rota = Rotation(Vector(0, 0, 1), axisdegree.z) v = rota.multVec(v) if axisdegree.y != 0: rota = Rotation(Vector(0, 1, 0), axisdegree.y) v = rota.multVec(v) if axisdegree.x != 0: rota = Rotation(Vector(1, 0, 0), axisdegree.x) v = rota.multVec(v) newlist.append(v) return newlist
def test_export_with_translated_part_containing_translated_link_to_primitive( self): test_package_path = Path(__file__).parent cube_document = App.newDocument('Cube') box = cube_document.addObject('Part::Box', 'Box') box.Label = 'Cube' cube_document_path = test_package_path.joinpath('Cube.FCStd') cube_document.saveAs(str(cube_document_path)) part_document = App.newDocument('Part') part_document_path = test_package_path.joinpath('Part.FCStd') part_document.saveAs(str(part_document_path)) box_link = part_document.addObject('App::Link', 'Link') box_link.setLink(box) box_link.Label = box.Label box_link.LinkPlacement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) part = part_document.addObject('App::Part', 'Part') part.addObject(box_link) part.Placement = Placement(Vector(5, 0, 0), Rotation(Vector(0, 0, 1), 0)) part_document.recompute() with open( os.path.join(os.path.dirname(__file__), 'translated_cube.obj')) as f: expected = f.read() obj_file_contents = freecad_to_obj.export([part]) self.assertEqual(obj_file_contents, expected) cube_document_path.unlink() part_document_path.unlink()
def test_export_with_translated_sphere(self): document = App.newDocument() sphere = document.addObject('Part::Sphere', 'Sphere') sphere.Label = 'Sphere' sphere.Placement = Placement(Vector(10, 0, 0), Rotation(Vector(0, 0, 1), 0)) document.recompute() with open( os.path.join(os.path.dirname(__file__), 'translated_sphere.obj')) as f: expected = f.read() obj_file_contents = freecad_to_obj.export([sphere]) self.assertEqual(obj_file_contents, expected)
def createAlonePlane(shape, angleZ=0, size=100): ''' Создат плоскость проходящую через ось объекта под углом angleZ к оси Z ''' # определение вектора основной оси объекта axis = findMainAxis(shape) dirX = (axis.Vertexes[1].Point - axis.Vertexes[0].Point).normalize() plane = Part.makePlane(size, size) plane.Placement.Rotation = Rotation(Vector(1, 0, 0), dirX) plane.Placement.Base = axis.CenterOfMass - dirX * size / 2 rotateL(plane, (1, 0, 0), angleZ) return plane
def get_placement(orientation, side, box_height, length, motor_box_length): try: return { CoordinateAxis.X: { Side.TOP: Placement() }, CoordinateAxis.Y: { Side.LEFT: Placement(Vector(box_height, length, 0), Rotation(-90, 0, 90)), Side.RIGHT: Placement(Vector(0, length, motor_box_length), Rotation(-90, 0, -90)) }, CoordinateAxis.Z: { Side.FRONT: Placement(Vector(0, box_height, length), Rotation(0, 90, 90)), Side.REAR: Placement(Vector(motor_box_length, 0, length), Rotation(0, 90, -90)) } }[orientation][side] except KeyError: message = 'Invalid combination of orientation "{}" and side "{}" passed.' raise ValueError(message.format(orientation, side))
def make_steps(rail_dist, step_rail_gap, step_diam, first_step, padding, L_thickness, n_steps, step_dist): step_length = rail_dist - 2 * L_thickness - 2 * step_rail_gap cyl = doc.addObject("Part::Cylinder", "Cylinder") cyl.Height = step_length cyl.Radius = step_diam / 2 shift = [ first_step, (rail_dist - step_length) / 2, step_diam / 2 + padding + L_thickness ] cyl.Placement = Placement(Vector(shift), Rotation(Vector(1, 0, 0), -90)) obj = Draft.makeArray(cyl, Vector(step_dist, 0, 0), Vector(0, 1, 0), n_steps, 1) Draft.autogroup(obj) return obj
def getRotation(self): """Return quaternion from the transformation matrix. """ # the trace is the sum of the diagonal elements; see http://mathworld.wolfram.com/MatrixTrace.html xx = self.m[0][0] xy = self.m[0][1] xz = self.m[0][2] yx = self.m[1][0] yy = self.m[1][1] yz = self.m[1][2] zx = self.m[2][0] zy = self.m[2][1] zz = self.m[2][2] t = xx + yy + zz # we protect the division by s by ensuring that s>=1 if (t >= 0): # |w| >= .5 s = math.sqrt(t + 1) # |s|>=1 ... w = 0.5 * s s = 0.5 / s # so this division isn't bad x = (zy - yz) * s y = (xz - zx) * s z = (yx - xy) * s elif ((xx > yy) and (xx > zz)): s = math.sqrt(1.0 + xx - yy - zz) # |s|>=1 x = s * 0.5 #|x| >= 0.5 s = 0.5 / s y = (yx + xy) * s z = (xz + zx) * s w = (zy - yz) * s elif (yy > zz): s = math.sqrt(1.0 - xx + yy - zz) # |s|>=1 y = s * 0.5 # |y| >= 0.5 s = 0.5 / s x = (yx + xy) * s z = (zy + yz) * s w = (xz - zx) * s else: s = math.sqrt(1.0 + zz - xx - yy) # |s|>=1 z = s * 0.5 # |z| >= 0.5 s = 0.5 / s x = (xz + zx) * s y = (zy + yz) * s w = (yx - xy) * s return Rotation(x, y, z, w)
def test_get_axis_frame_attachment_kwargs_for_front_face(self): front_face = self.frame.Proxy.get_faces_for_side(Side.FRONT)[0] result = get_axis_frame_attachment_kwargs(self.frame, front_face, CoordinateAxis.Z) expected = { 'origin_translation_offset': Vector(-0.5, -1.0, 0.0), 'placement': Placement(Vector(self.frame.Size / 2, 0, 0), Rotation(), Vector()), 'orientation': CoordinateAxis.Z, 'side': Side.FRONT } self.assert_result_and_expected_are_equal(result, expected)
def get_heated_bed_frame_axis_attachment_kwargs(frame, axis) -> dict: """Get a dictionary describing how to attach a heated bed to a frame and axis. :param frame: Frame object to attach heated bed to. :param axis: Axis object to attach heated bed to. :return: Dictionary describing how to attach a heated bed to a frame and axis. """ _validate_frame(frame) _validate_axis(axis) x = frame.Shape.BoundBox.Center.x y = frame.Shape.BoundBox.Center.y z = axis.Proxy.calculate_top_of_carriage_box_for_z_axis() placement = Placement(Vector(x, y, z), Rotation()) origin_translation_offset = Vector(-0.5, -0.5, 0) return { 'placement': placement, 'origin_translation_offset': origin_translation_offset }
def test_get_axis_frame_attachment_kwargs_for_right_face(self): right_face = self.frame.Proxy.get_faces_for_side(Side.RIGHT)[0] result = get_axis_frame_attachment_kwargs(self.frame, right_face, CoordinateAxis.Y) expected = { 'origin_translation_offset': Vector(0.0, 0.0, -1.0), 'placement': Placement(Vector(self.frame.Size, 0, self.frame.Size), Rotation(), Vector()), 'orientation': CoordinateAxis.Y, 'side': Side.RIGHT } self.assert_result_and_expected_are_equal(result, expected)
def test_get_axis_frame_attachment_kwargs_for_top_face(self): top_face = self.frame.Proxy.get_faces_for_side(Side.TOP)[0] result = get_axis_frame_attachment_kwargs(self.frame, top_face, CoordinateAxis.X) expected = { 'origin_translation_offset': Vector(0.0, -0.5, 0.0), 'placement': Placement(Vector(0, self.frame.Size / 2, self.frame.Size), Rotation()), 'orientation': CoordinateAxis.X, 'side': Side.TOP } self.assert_result_and_expected_are_equal(result, expected)
def createCrossPlane(shape, pos=0, size=100): ''' createCrossPlane(shape, pos=0, size=100) Создает плоскость пересекающую объект перпендикулярно в центре ''' axis = findMainAxis(shape) dir = (axis.Vertexes[1].Point - axis.Vertexes[0].Point).normalize() p = Part.makePlane(size, size) p.Placement.Rotation = Rotation(Vector(0, 0, 1), dir) p.Placement.Base = axis.CenterOfMass - p.CenterOfMass sax, say, saz = getAxes(shape) pax, pay, paz = getAxes(p) rotateL(p, (0, 0, 1), say.getAngle(pay) * 360 / (math.pi * 2), p.CenterOfMass) moveL(p, (0, 0, 1), pos) return p
def test_export_with_object_name_getter(self): document = App.newDocument() box = document.addObject('Part::Box', 'CubeLink') box.Label = 'Cube' box.Placement = Placement(Vector(10, 0, 0), Rotation(Vector(0, 0, 1), 0)) document.recompute() obj_filename = 'link_to_translated_cube.obj' with open(os.path.join(os.path.dirname(__file__), obj_filename)) as f: expected = f.read() def object_name_getter(obj: object, path: List[object]) -> str: return obj.Name obj_file_contents = freecad_to_obj.export( [box], object_name_getter=object_name_getter) self.assertEqual(obj_file_contents, expected)
def createCutPie(shape, segment=45, angle=0, pos=0, height=2, axis=None, radius=None, placement=None): '''Создает сегмент который режет shape перпендикулярно оси shape shape - основное тело segment - угловой размер сегмента в градусах angle - угол начала сегмента относительно оси Z в градусах pos - положение сегмента относительно центра масс shape height - толщина сегмента axis - основная ось shape radius - ''' if not placement: placement = shape.Placement if not axis: edge = findMainAxis(shape) axis = edge.Vertexes[1].Point - edge.Vertexes[0].Point if not radius: lmin, lmax = shapeSize(shape) radius = max(lmax.y - lmin.y, lmax.z - lmin.z) / 2 if height: s = Part.makeCylinder(radius, height, Vector(0, 0, 0), Vector(0, 0, 1), segment) else: s = Part.makeCircle(radius, Vector(0, 0, 0), Vector(0, 0, 1), 0, segment) s.Placement.Rotation = Rotation(Vector(0, 0, 1), axis) ax, ay, az = getAxes(placement) sax, say, saz = getAxes(s) rotateL(s, (0, 0, 1), ay.getAngle(sax) * 360 / (2 * math.pi)) rotateL(s, (1, 0, 0), 180) s.Placement.Base = edge.CenterOfMass moveL(s, (0, 0, 1), pos - height / 2) return s
def test_get_axis_frame_attachment_kwargs_for_rear_face(self): rear_faces = self.frame.Proxy.get_faces_for_side(Side.REAR) for rear_face in rear_faces: result = get_axis_frame_attachment_kwargs(self.frame, rear_face, 'z') expected = { 'origin_translation_offset': Vector(-0.5, 0, 0), 'placement': Placement(Vector(self.frame.Size / 2, self.frame.Size, 0), Rotation(), Vector()), 'length_value': self.frame.Size.Value, 'orientation': CoordinateAxis.Z, 'side': Side.REAR } self.assert_result_and_expected_are_equal(result, expected)
def _get_placement_by_corner(length: float) -> Dict[str, Placement]: return { Corner.BOTTOM_LEFT_FRONT: Placement(), Corner.BOTTOM_LEFT_REAR: Placement(Vector(0, length, 0), Rotation(-90, 0, 0)), Corner.BOTTOM_RIGHT_REAR: Placement(Vector(length, length, 0), Rotation(180, 0, 0)), Corner.BOTTOM_RIGHT_FRONT: Placement(Vector(length, 0, 0), Rotation(90, 0, 0)), Corner.TOP_LEFT_FRONT: Placement(Vector(0, 0, length), Rotation(0, 90, 0)), Corner.TOP_LEFT_REAR: Placement(Vector(0, length, length), Rotation(-90, 90, 0)), Corner.TOP_RIGHT_REAR: Placement(Vector(length, length, length), Rotation(90, 180, 0)), Corner.TOP_RIGHT_FRONT: Placement(Vector(length, 0, length), Rotation(0, 180, 0)) }
def createTopCone(face, placement, pos=30, r_angle=0, segment=45, height=2): '''Создает конус рассекающий сферическую поверхность face - рассекаемая поверхность placement - базис поверхности в ГСК pos - удаление контура от центра рассекаемой поверхности r_angle - начальный угол в градусах segment - угловой размер в градусах height - толщина конуса ''' radius = face.Surface.Radius cone_height = math.sqrt(radius**2 - pos**2) cone = Part.makeCone(0, pos, cone_height, Vector(0, 0, 0), Vector(0, 0, 1), segment) ax, ay, az = getAxes(placement) cone.Placement.Rotation = Rotation(Vector(0, 0, 1), ax) sax, say, saz = getAxes(cone) #rotateL(s, (1,0,0), 180) cone.Placement.Base = placement.Base return cone