class OCSTransform: def __init__(self, extrusion: Vec3 = None, m: Matrix44 = None): self.m = m if extrusion is None: self.old_ocs = None self.scale_uniform = False self.new_ocs = None else: self.old_ocs = OCS(extrusion) new_extrusion, self.scale_uniform = transform_extrusion(extrusion, m) self.new_ocs = OCS(new_extrusion) @property def old_extrusion(self) -> Vec3: return self.old_ocs.uz @property def new_extrusion(self) -> Vec3: return self.new_ocs.uz @classmethod def from_ocs(cls, old: OCS, new: OCS, m: Matrix44) -> 'OCSTransform': ocs = cls() ocs.m = m ocs.old_ocs = old ocs.new_ocs = new return ocs def transform_length(self, length: 'Vertex', reflection=1.0) -> float: """ Returns magnitude of `length` direction vector transformed from old OCS into new OCS including `reflection` correction applied. """ return self.m.transform_direction(self.old_ocs.to_wcs(length)).magnitude * sign(reflection) transform_scale_factor = transform_length def transform_vertex(self, vertex: 'Vertex') -> Vec3: """ Returns vertex transformed from old OCS into new OCS. """ return self.new_ocs.from_wcs(self.m.transform(self.old_ocs.to_wcs(vertex))) def transform_2d_vertex(self, vertex: 'Vertex', elevation: float) -> Vec2: """ Returns 2D vertex transformed from old OCS into new OCS. """ v = Vec3(vertex).replace(z=elevation) return self.new_ocs.from_wcs(self.m.transform(self.old_ocs.to_wcs(v))).vec2 def transform_direction(self, direction: 'Vertex') -> Vec3: """ Returns direction transformed from old OCS into new OCS. """ return self.new_ocs.from_wcs(self.m.transform_direction(self.old_ocs.to_wcs(direction))) def transform_angle(self, angle: float) -> float: """ Returns angle (in radians) from old OCS transformed into new OCS. """ return self.transform_direction(Vec3.from_angle(angle)).angle def transform_deg_angle(self, angle: float) -> float: """ Returns angle (in degrees) from old OCS transformed into new OCS. """ return math.degrees(self.transform_angle(math.radians(angle)))
def to_ocs(self) -> "ConstructionEllipse": """Returns ellipse parameters as OCS representation. OCS elevation is stored in :attr:`center.z`. """ ocs = OCS(self.extrusion) return self.__class__( center=ocs.from_wcs(self.center), major_axis=ocs.from_wcs( self.major_axis).replace(z=0), # type: ignore ratio=self.ratio, start_param=self.start_param, end_param=self.end_param, )
def create_block_references( layout: 'BaseLayout', block_name: str, layer: str = "LAYER", grid=(10, 10), extrusions=((0, 0, 1), (0, 0, -1)), scales=((1, 1, 1), (-1, 1, 1), (1, -1, 1), (1, 1, -1)), angles=(0, 45, 90, 135, 180, 225, 270, 315), ): y = 0 grid_x, grid_y = grid for extrusion in extrusions: ocs = OCS(extrusion) for sx, sy, sz in scales: for index, angle in enumerate(angles): x = index * grid_x insert = ocs.from_wcs((x, y)) blk_ref = layout.add_blockref(block_name, insert, dxfattribs={ 'layer': layer, 'rotation': angle, 'xscale': sx, 'yscale': sy, 'zscale': sz, 'extrusion': extrusion, }) show_config(blk_ref) y += grid_y
def test_to_ocs(self): p = Path((0, 1, 1)) p.line_to((0, 1, 3)) ocs = OCS((1, 0, 0)) # x-Axis result = list(transform_paths_to_ocs([p], ocs)) p0 = result[0] assert ocs.from_wcs((0, 1, 1)) == p0.start assert ocs.from_wcs((0, 1, 3)) == p0[0].end
def _update_location_from_mtext(text: Text, mtext: MText) -> None: # TEXT is an OCS entity, MTEXT is a WCS entity dxf = text.dxf insert = Vec3(mtext.dxf.insert) extrusion = Vec3(mtext.dxf.extrusion) text_direction = mtext.get_text_direction() if extrusion.isclose(Z_AXIS): # most common case dxf.rotation = text_direction.angle_deg else: ocs = OCS(extrusion) insert = ocs.from_wcs(insert) dxf.extrusion = extrusion.normalize() dxf.rotation = ocs.from_wcs(text_direction).angle_deg # type: ignore dxf.insert = insert dxf.align_point = insert # the same point for all MTEXT alignments! dxf.halign, dxf.valign = MAP_MTEXT_ALIGN_TO_FLAGS.get( mtext.dxf.attachment_point, (TextHAlign.LEFT, TextVAlign.TOP))
def test_wcs_to_ocs(): ocs = OCS(EXTRUSION) assert is_close_points( ocs.from_wcs((-9.56460754, 8.44764172, 9.97894327)), (9.41378764657076, 13.15481838975576, 0.8689258932616031), places=6, ) assert is_close_points( ocs.from_wcs((-1.60085321, 9.29648008, 1.85322122)), (9.41378764657076, 1.745643639268379, 0.8689258932616031), places=6, ) assert is_close_points( ocs.from_wcs((-3.56027455, 9.08762984, 3.85249348)), (9.41378764657076, 4.552784531093068, 0.8689258932616031), places=6, ) assert is_close_points( ocs.from_wcs((-5.53851623, 8.87677359, 5.87096886)), (9.41378764657076, 7.386888158025531, 0.8689258932616031), places=6, )
def test_circle_user_ocs(): center = (2, 3, 4) extrusion = (0, 1, 0) circle = Circle.new( dxfattribs={'center': center, 'extrusion': extrusion, 'thickness': 2}) ocs = OCS(extrusion) v = ocs.to_wcs(center) # (-2, 4, 3) v = Vector(v.x * 2, v.y * 4, v.z * 2) v += (1, 1, 1) # and back to OCS, extrusion is unchanged result = ocs.from_wcs(v) m = Matrix44.chain(Matrix44.scale(2, 4, 2), Matrix44.translate(1, 1, 1)) circle.transform(m) assert circle.dxf.center == result assert circle.dxf.extrusion == (0, 1, 0) assert circle.dxf.thickness == 8 # in WCS y-axis
def main(filename): doc = ezdxf.new('R2010') msp = doc.modelspace() origin = (3, 3, 3) axis = (1, 0, -1) def_point = (3, 10, 4) ucs = UCS.from_z_axis_and_point_in_yz(origin, axis=axis, point=def_point) ucs.render_axis(msp, length=5) msp.add_point(location=def_point, dxfattribs={'color': 2}) ocs = OCS(ucs.uz) msp.add_circle(center=ocs.from_wcs(origin), radius=1, dxfattribs={ 'color': 2, 'extrusion': ucs.uz, }) doc.saveas(filename)
def _get_ocs(extrusion: Vec3, referenc_point: Vec3) -> Tuple[OCS, float]: ocs = OCS(extrusion) elevation = ocs.from_wcs(referenc_point).z return ocs, elevation
# include-start import ezdxf from ezdxf.math import OCS doc = ezdxf.new('R2010') msp = doc.modelspace() # For this example the OCS is rotated around x-axis about 45 degree # OCS z-axis: x=0, y=1, z=1 # extrusion vector must not normalized here ocs = OCS((0, 1, 1)) msp.add_circle( # You can place the 2D circle in 3D space # but you have to convert WCS into OCS center=ocs.from_wcs((0, 2, 2)), # center in OCS: (0.0, 0.0, 2.82842712474619) radius=1, dxfattribs={ # here the extrusion vector should be normalized, # which is granted by using the ocs.uz 'extrusion': ocs.uz, 'color': 1, }) # mark center point of circle in WCS msp.add_point((0, 2, 2), dxfattribs={'color': 1}) # include-end print("center in OCS: {}".format(ocs.from_wcs((0, 2, 2)))) ocs.render_axis(msp) doc.saveas('ocs_circle.dxf')
OUT_DIR = Path('~/Desktop/Outbox').expanduser() import ezdxf from ezdxf.math import OCS doc = ezdxf.new('R2010') msp = doc.modelspace() # For this example the OCS is rotated around x-axis about 45 degree # OCS z-axis: x=0, y=1, z=1 # extrusion vector must not normalized here ocs = OCS((0, 1, 1)) msp.add_circle( # You can place the 2D circle in 3D space # but you have to convert WCS into OCS center=ocs.from_wcs((0, 2, 2)), # center in OCS: (0.0, 0.0, 2.82842712474619) radius=1, dxfattribs={ # here the extrusion vector should be normalized, # which is granted by using the ocs.uz 'extrusion': ocs.uz, 'color': 1, }) # mark center point of circle in WCS msp.add_point((0, 2, 2), dxfattribs={'color': 1}) print(f"center in OCS: {ocs.from_wcs((0, 2, 2))}") ocs.render_axis(msp) doc.saveas(OUT_DIR / 'ocs_circle.dxf')