def _calcTransforms(self): """Computes transformation matrices to convert between coordinates Computes transformation matrices to convert between local and global coordinates. """ # r is the forward transformation matrix from world to local coordinates # ok i will be really honest, i cannot understand exactly why this works # something bout the order of the translation and the rotation. # the double-inverting is strange, and I don't understand it. forward = Matrix() inverse = Matrix() forwardT = gp_Trsf() inverseT = gp_Trsf() global_coord_system = gp_Ax3() local_coord_system = gp_Ax3( gp_Pnt(*self.origin.toTuple()), gp_Dir(*self.zDir.toTuple()), gp_Dir(*self.xDir.toTuple()), ) forwardT.SetTransformation(global_coord_system, local_coord_system) forward.wrapped = gp_GTrsf(forwardT) inverseT.SetTransformation(local_coord_system, global_coord_system) inverse.wrapped = gp_GTrsf(inverseT) self.lcs = local_coord_system self.rG = inverse self.fG = forward
def _dxf_circle(e: Edge, msp: ezdxf.layouts.Modelspace, plane: Plane): geom = e._geomAdaptor() circ = geom.Circle() r = circ.Radius() c = circ.Location() c_dy = circ.YAxis().Direction() c_dz = circ.Axis().Direction() dy = gp_Dir(0, 1, 0) phi = c_dy.AngleWithRef(dy, c_dz) if c_dz.XYZ().Z() > 0: a1 = RAD2DEG * (geom.FirstParameter() - phi) a2 = RAD2DEG * (geom.LastParameter() - phi) else: a1 = -RAD2DEG * (geom.LastParameter() + phi) a2 = -RAD2DEG * (geom.FirstParameter() + phi) if e.IsClosed(): msp.add_circle((c.X(), c.Y(), c.Z()), r) else: msp.add_arc((c.X(), c.Y(), c.Z()), r, a1, a2)
def rotated(self, rotate=(0, 0, 0)): """Returns a copy of this plane, rotated about the specified axes Since the z axis is always normal the plane, rotating around Z will always produce a plane that is parallel to this one. The origin of the workplane is unaffected by the rotation. Rotations are done in order x, y, z. If you need a different order, manually chain together multiple rotate() commands. :param rotate: Vector [xDegrees, yDegrees, zDegrees] :return: a copy of this plane rotated as requested. """ # NB: this is not a geometric Vector rotate = Vector(rotate) # Convert to radians. rotate = rotate.multiply(math.pi / 180.0) # Compute rotation matrix. T1 = gp_Trsf() T1.SetRotation( gp_Ax1(gp_Pnt(*(0, 0, 0)), gp_Dir(*self.xDir.toTuple())), rotate.x) T2 = gp_Trsf() T2.SetRotation( gp_Ax1(gp_Pnt(*(0, 0, 0)), gp_Dir(*self.yDir.toTuple())), rotate.y) T3 = gp_Trsf() T3.SetRotation( gp_Ax1(gp_Pnt(*(0, 0, 0)), gp_Dir(*self.zDir.toTuple())), rotate.z) T = Matrix(gp_GTrsf(T1 * T2 * T3)) # Compute the new plane. newXdir = self.xDir.transform(T) newZdir = self.zDir.transform(T) return Plane(self.origin, newXdir, newZdir)
def addLines(self): origin = (0, 0, 0) ais_list = [] for name, color, direction in zip(('X', 'Y', 'Z'), ('red', 'lawngreen', 'blue'), ((1, 0, 0), (0, 1, 0), (0, 0, 1))): line_placement = Geom_Line( gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction))) line = AIS_Line(line_placement) line.SetColor(to_occ_color(color)) self.Helpers.addChild(ObjectTreeItem(name, ais=line)) ais_list.append(line) self.sigObjectsAdded.emit(ais_list)
def fixed_axis_cost(m1: gp_Dir, t1: gp_Trsf, val: Tuple[float, float, float]): return DIR_SCALING * (m1.Transformed(t1).Angle(gp_Dir(*val)))
def toDir(self) -> gp_Dir: return gp_Dir(self.wrapped.XYZ())
def show_axis(self,origin = (0,0,0), direction=(0,0,1)): ax_placement = Geom_Axis1Placement(gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction))) ax = AIS_Axis(ax_placement) self._display_ais(ax)
import io as StringIO from ..shapes import Shape, Compound, TOLERANCE from ..geom import BoundBox from OCP.gp import gp_Ax2, gp_Pnt, gp_Dir from OCP.BRepLib import BRepLib from OCP.HLRBRep import HLRBRep_Algo, HLRBRep_HLRToShape from OCP.HLRAlgo import HLRAlgo_Projector from OCP.GCPnts import GCPnts_QuasiUniformDeflection DISCRETIZATION_TOLERANCE = 1e-3 DEFAULT_DIR = gp_Dir(-1.75, 1.1, 5) SVG_TEMPLATE = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="%(width)s" height="%(height)s" > <g transform="scale(%(unitScale)s, -%(unitScale)s) translate(%(xTranslate)s,%(yTranslate)s)" stroke-width="%(strokeWidth)s" fill="none"> <!-- hidden lines --> <g stroke="rgb(160, 160, 160)" fill="none" stroke-dasharray="%(strokeWidth)s,%(strokeWidth)s" > %(hiddenContent)s </g> <!-- solid lines --> <g stroke="rgb(0, 0, 0)" fill="none"> %(visibleContent)s
def show_line(self,origin = (0,0,0), direction=(0,0,1)): line_placement = Geom_Line(gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction))) line = AIS_Line(line_placement) self._display_ais(line)
def getSVG(shape, opts=None): """ Export a shape to SVG text. :param shape: A CadQuery shape object to convert to an SVG string. :type Shape: Vertex, Edge, Wire, Face, Shell, Solid, or Compound. :param opts: An options dictionary that influences the SVG that is output. :type opts: Dictionary, keys are as follows: width: Document width of the resulting image. height: Document height of the resulting image. marginLeft: Inset margin from the left side of the document. marginTop: Inset margin from the top side of the document. projectionDir: Direction the camera will view the shape from. showAxes: Whether or not to show the axes indicator, which will only be visible when the projectionDir is also at the default. strokeWidth: Width of the line that visible edges are drawn with. strokeColor: Color of the line that visible edges are drawn with. hiddenColor: Color of the line that hidden edges are drawn with. showHidden: Whether or not to show hidden lines. """ # Available options and their defaults d = { "width": 800, "height": 240, "marginLeft": 200, "marginTop": 20, "projectionDir": (-1.75, 1.1, 5), "showAxes": True, "strokeWidth": -1.0, # -1 = calculated based on unitScale "strokeColor": (0, 0, 0), # RGB 0-255 "hiddenColor": (160, 160, 160), # RGB 0-255 "showHidden": True, } if opts: d.update(opts) # need to guess the scale and the coordinate center uom = guessUnitOfMeasure(shape) width = float(d["width"]) height = float(d["height"]) marginLeft = float(d["marginLeft"]) marginTop = float(d["marginTop"]) projectionDir = tuple(d["projectionDir"]) showAxes = bool(d["showAxes"]) strokeWidth = float(d["strokeWidth"]) strokeColor = tuple(d["strokeColor"]) hiddenColor = tuple(d["hiddenColor"]) showHidden = bool(d["showHidden"]) hlr = HLRBRep_Algo() hlr.Add(shape.wrapped) projector = HLRAlgo_Projector(gp_Ax2(gp_Pnt(), gp_Dir(*projectionDir))) hlr.Projector(projector) hlr.Update() hlr.Hide() hlr_shapes = HLRBRep_HLRToShape(hlr) visible = [] visible_sharp_edges = hlr_shapes.VCompound() if not visible_sharp_edges.IsNull(): visible.append(visible_sharp_edges) visible_smooth_edges = hlr_shapes.Rg1LineVCompound() if not visible_smooth_edges.IsNull(): visible.append(visible_smooth_edges) visible_contour_edges = hlr_shapes.OutLineVCompound() if not visible_contour_edges.IsNull(): visible.append(visible_contour_edges) hidden = [] hidden_sharp_edges = hlr_shapes.HCompound() if not hidden_sharp_edges.IsNull(): hidden.append(hidden_sharp_edges) hidden_contour_edges = hlr_shapes.OutLineHCompound() if not hidden_contour_edges.IsNull(): hidden.append(hidden_contour_edges) # Fix the underlying geometry - otherwise we will get segfaults for el in visible: BRepLib.BuildCurves3d_s(el, TOLERANCE) for el in hidden: BRepLib.BuildCurves3d_s(el, TOLERANCE) # convert to native CQ objects visible = list(map(Shape, visible)) hidden = list(map(Shape, hidden)) (hiddenPaths, visiblePaths) = getPaths(visible, hidden) # get bounding box -- these are all in 2D space bb = Compound.makeCompound(hidden + visible).BoundingBox() # width pixels for x, height pixels for y unitScale = min(width / bb.xlen * 0.75, height / bb.ylen * 0.75) # compute amount to translate-- move the top left into view (xTranslate, yTranslate) = ( (0 - bb.xmin) + marginLeft / unitScale, (0 - bb.ymax) - marginTop / unitScale, ) # If the user did not specify a stroke width, calculate it based on the unit scale if strokeWidth == -1.0: strokeWidth = 1.0 / unitScale # compute paths hiddenContent = "" # Prevent hidden paths from being added if the user disabled them if showHidden: for p in hiddenPaths: hiddenContent += PATHTEMPLATE % p visibleContent = "" for p in visiblePaths: visibleContent += PATHTEMPLATE % p # If the caller wants the axes indicator and is using the default direction, add in the indicator if showAxes and projectionDir == (-1.75, 1.1, 5): axesIndicator = AXES_TEMPLATE % ({ "unitScale": str(unitScale), "textboxY": str(height - 30), "uom": str(uom) }) else: axesIndicator = "" svg = SVG_TEMPLATE % ( { "unitScale": str(unitScale), "strokeWidth": str(strokeWidth), "strokeColor": ",".join([str(x) for x in strokeColor]), "hiddenColor": ",".join([str(x) for x in hiddenColor]), "hiddenContent": hiddenContent, "visibleContent": visibleContent, "xTranslate": str(xTranslate), "yTranslate": str(yTranslate), "width": str(width), "height": str(height), "textboxY": str(height - 30), "uom": str(uom), "axesIndicator": axesIndicator, }) return svg