def draw_viewport_entity(self, entity: DXFGraphic) -> None: assert entity.dxftype() == 'VIEWPORT' dxf = entity.dxf view_vector: Vector = dxf.view_direction_vector mag = view_vector.magnitude if math.isclose(mag, 0.0): self.log_message('Warning: viewport with null view vector') return view_vector /= mag if not math.isclose(view_vector.dot(Vector(0, 0, 1)), 1.0): self.log_message( f'Cannot render viewport with non-perpendicular view direction:' f' {dxf.view_direction_vector}') return cx, cy = dxf.center.x, dxf.center.y dx = dxf.width / 2 dy = dxf.height / 2 minx, miny = cx - dx, cy - dy maxx, maxy = cx + dx, cy + dy points = [(minx, miny), (maxx, miny), (maxx, maxy), (minx, maxy), (minx, miny)] props = Properties() props.color = VIEWPORT_COLOR # Set default SOLID filling for VIEWPORT props.filling = Filling() self.out.draw_filled_polygon([Vector(x, y, 0) for x, y in points], props)
def draw_wipeout_entity(self, entity: DXFGraphic, properties: Properties) -> None: wipeout = cast(Wipeout, entity) properties.filling = Filling() properties.color = self.ctx.current_layout.background_color path = wipeout.boundary_path_wcs() self.out.draw_filled_polygon(path, properties)
def draw_viewport_entity(self, entity: DXFGraphic, properties: Properties) -> None: assert entity.dxftype() == 'VIEWPORT' # Special VIEWPORT id == 1, this viewport defines the "active viewport" # which is the area currently shown in the layout tab by the CAD # application. # BricsCAD set id to -1 if the viewport is off and 'status' (group # code 68) is not present. if entity.dxf.id < 2 or entity.dxf.status < 1: return dxf = entity.dxf view_vector: Vec3 = dxf.view_direction_vector mag = view_vector.magnitude if math.isclose(mag, 0.0): self.log_message('Warning: viewport with null view vector') return view_vector /= mag if not math.isclose(view_vector.dot(Vec3(0, 0, 1)), 1.0): self.log_message( f'Cannot render viewport with non-perpendicular view direction:' f' {dxf.view_direction_vector}') return cx, cy = dxf.center.x, dxf.center.y dx = dxf.width / 2 dy = dxf.height / 2 minx, miny = cx - dx, cy - dy maxx, maxy = cx + dx, cy + dy points = [(minx, miny), (maxx, miny), (maxx, maxy), (minx, maxy), (minx, miny)] props = Properties() props.color = VIEWPORT_COLOR # Set default SOLID filling for VIEWPORT props.filling = Filling() self.out.draw_filled_polygon([Vec3(x, y, 0) for x, y in points], props)
def finalize(self) -> None: super().finalize() self._scene.setSceneRect(self._scene.itemsBoundingRect()) if self._debug_draw_rect: properties = Properties() properties.color = '#000000' self._scene.addRect(self._scene.sceneRect(), self._get_pen(properties), self._no_fill)
def draw_solid_entity(self, entity: DXFGraphic, properties: Properties) -> None: if isinstance(entity, Face3d): dxf = entity.dxf try: # this implementation supports all features of example file: # examples_dxf/3dface.dxf without changing the behavior of # Face3d.wcs_vertices() which removes the last vertex if # duplicated. points = [dxf.vtx0, dxf.vtx1, dxf.vtx2, dxf.vtx3, dxf.vtx0] except AttributeError: # all 4 vertices are required, otherwise the entity is invalid # for AutoCAD self.skip_entity(entity, "missing required vertex attribute") return edge_visibility = entity.get_edges_visibility() if all(edge_visibility): self.out.draw_path(from_vertices(points), properties) else: for a, b, visible in zip(points, points[1:], edge_visibility): if visible: self.out.draw_line(a, b, properties) elif isinstance(entity, Solid): # set solid fill type for SOLID and TRACE properties.filling = Filling() self.out.draw_filled_polygon(entity.wcs_vertices(close=False), properties) else: raise TypeError( "API error, requires a SOLID, TRACE or 3DFACE entity")
def _draw_rect( self, bottom_left: Tuple[float, float], top_right: Tuple[float, float], color: str, ) -> None: minx, miny = bottom_left maxx, maxy = top_right points = [ (minx, miny), (maxx, miny), (maxx, maxy), (minx, maxy), (minx, miny), ] props = Properties() props.color = color # default SOLID filling props.filling = Filling() self.out.draw_filled_polygon([Vec3(x, y, 0) for x, y in points], props)
def override_properties(self, entity: DXFGraphic, properties: Properties) -> None: """ The :meth:`override_properties` filter can change the properties of an entity independent from the DXF attributes. This filter has access to the DXF attributes by the `entity` object, the current render context, and the resolved properties by the `properties` object. It is recommended to modify only the `properties` object in this filter. """ if entity.dxftype() == 'HATCH': properties.color = set_color_alpha(properties.color, 200)
def draw_solid_entity(self, entity: DXFGraphic, properties: Properties) -> None: assert isinstance(entity, (Solid, Face3d)), \ "API error, requires a SOLID, TRACE or 3DFACE entity" dxf, dxftype = entity.dxf, entity.dxftype() points = entity.wcs_vertices() if dxftype == '3DFACE': self.out.draw_path(from_vertices(points, close=True), properties) else: # set solid fill type for SOLID and TRACE properties.filling = Filling() self.out.draw_filled_polygon(points, properties)
def draw_mpolygon_entity(self, entity: DXFGraphic, properties: Properties): def resolve_fill_color() -> str: return self.ctx.resolve_aci_color(entity.dxf.fill_color, properties.layer) polygon = cast(DXFPolygon, entity) ocs = polygon.ocs() elevation: float = polygon.dxf.elevation.z offset = Vec3(polygon.dxf.get("offset_vector", NULLVEC)) # MPOLYGON does not support hatch styles, all paths are rendered. loops = closed_loops(polygon.paths, ocs, elevation, offset) line_color: str = properties.color assert properties.filling is not None pattern_name: str = properties.filling.name # normalized pattern name # 1. draw filling if polygon.dxf.solid_fill: properties.filling.type = Filling.SOLID if (polygon.gradient is not None and polygon.gradient.number_of_colors > 0): # true color filling is stored as gradient properties.color = str(properties.filling.gradient_color1) else: properties.color = resolve_fill_color() self.draw_hatch_entity(entity, properties, loops=loops) # checking properties.filling.type == Filling.PATTERN is not sufficient: elif pattern_name and pattern_name != "SOLID": # line color is also pattern color: properties.color self.draw_hatch_entity(entity, properties, loops=loops) # 2. draw boundary paths properties.color = line_color # draw boundary paths as lines for loop in loops: self.out.draw_path(loop, properties)
def draw_solid_entity(self, entity: DXFGraphic, properties: Properties) -> None: # Handles SOLID, TRACE and 3DFACE dxf, dxftype = entity.dxf, entity.dxftype() points = get_tri_or_quad_points(entity, adjust_order=dxftype != '3DFACE') # TRACE is an OCS entity if dxftype == 'TRACE' and dxf.hasattr('extrusion'): ocs = entity.ocs() points = list(ocs.points_to_wcs(points)) if dxftype == '3DFACE': self.out.draw_path(from_vertices(points, close=True), properties) else: # Set default SOLID filling for SOLID and TRACE properties.filling = Filling() self.out.draw_filled_polygon(points, properties)
def draw_polyline_entity(self, entity: DXFGraphic, properties: Properties) -> None: dxftype = entity.dxftype() if dxftype == 'POLYLINE': e = cast(Polyface, entity) if e.is_polygon_mesh or e.is_poly_face_mesh: # draw 3D mesh or poly-face entity self.draw_mesh_builder_entity( MeshBuilder.from_polyface(e), properties, ) return entity = cast(Union[LWPolyline, Polyline], entity) is_lwpolyline = dxftype == 'LWPOLYLINE' if entity.has_width: # draw banded 2D polyline elevation = 0.0 ocs = entity.ocs() transform = ocs.transform if transform: if is_lwpolyline: # stored as float elevation = entity.dxf.elevation else: # stored as vector (0, 0, elevation) elevation = Vec3(entity.dxf.elevation).z trace = TraceBuilder.from_polyline( entity, segments=self.circle_approximation_count // 2 ) for polygon in trace.polygons(): # polygon is a sequence of Vec2() if transform: points = ocs.points_to_wcs( Vec3(v.x, v.y, elevation) for v in polygon ) else: points = Vec3.generate(polygon) # Set default SOLID filling for LWPOLYLINE properties.filling = Filling() self.out.draw_filled_polygon(points, properties) return path = Path.from_lwpolyline(entity) \ if is_lwpolyline else Path.from_polyline(entity) self.out.draw_path(path, properties)