def setup_pattern(): filling.type = Filling.PATTERN filling.name = hatch.dxf.pattern_name.upper() filling.pattern_scale = hatch.dxf.pattern_scale filling.angle = hatch.dxf.pattern_angle if hatch.dxf.pattern_double: # This value is not editable by CAD-App-GUI: filling.pattern_scale *= 2 # todo: is this correct? filling.pattern = self._hatch_pattern_cache.get(filling.name) if filling.pattern: return pattern = hatch.pattern if not pattern: return # DXF stores the hatch pattern already rotated and scaled, # pattern_scale and pattern_rotation are just hints for the CAD # application to modify the pattern if required. # It's better to revert the scaling and rotation, because in general # back-ends do not handle pattern that way, they need a base-pattern # and separated scaling and rotation attributes and these # base-pattern could be cached by their name. # # There is no advantage of simplifying the hatch line pattern and # this format is required by the PatternAnalyser(): filling.pattern = scale_pattern(pattern.as_list(), 1.0 / filling.pattern_scale, -filling.angle) self._hatch_pattern_cache[filling.name] = filling.pattern
def set_pattern_definition( self, lines: Sequence, factor: float = 1, angle: float = 0 ) -> None: """Setup pattern definition by a list of definition lines and a definition line is a 4-tuple (angle, base_point, offset, dash_length_items), the pattern definition should be designed for scaling factor 1 and angle 0. - angle: line angle in degrees - base-point: 2-tuple (x, y) - offset: 2-tuple (dx, dy) - dash_length_items: list of dash items (item > 0 is a line, item < 0 is a gap and item == 0.0 is a point) Args: lines: list of definition lines factor: pattern scaling factor angle: rotation angle in degrees """ if factor != 1 or angle: lines = pattern.scale_pattern(lines, factor=factor, angle=angle) self.pattern = Pattern( [PatternLine(line[0], line[1], line[2], line[3]) for line in lines] )
def resolve_filling(self, entity: 'DXFGraphic') -> Optional[Filling]: if entity.dxftype() == 'HATCH': hatch = cast('Hatch', entity) filling = Filling() if hatch.dxf.solid_fill: gradient = hatch.gradient if gradient is None: filling.type = Filling.SOLID else: if gradient.kind == 0: # Solid filling.type = Filling.SOLID filling.color1 = rgb_to_hex(gradient.color1) else: filling.type = Filling.GRADIENT filling.name = gradient.name.upper() filling.color1 = rgb_to_hex(gradient.color1) # todo: no idea when we should use aci1 filling.color2 = rgb_to_hex(gradient.color2) # todo: no idea when we should use aci2 filling.angle = gradient.rotation filling.gradient_tint = gradient.tint filling.gradient_centered = gradient.centered else: filling.type = Filling.PATTERN filling.name = hatch.dxf.pattern_name.upper() filling.pattern_scale = hatch.dxf.pattern_scale filling.angle = hatch.dxf.pattern_angle if hatch.dxf.pattern_double: # todo: ??? filling.pattern_scale *= 2 filling.pattern = self._hatch_pattern_cache.get(filling.name) if filling.pattern is None: pattern = hatch.pattern if pattern: # DXF stores the hatch pattern already rotated and scaled, # pattern_scale and pattern_rotation are just hints for # the CAD application, if they wanna change the pattern. # It's better to revert the scaling and rotation, # because in general back-ends do not handle pattern that way, # they need a base-pattern and separated scaling and rotation # attributes and these base-pattern could be cached by their name. base_pattern = scale_pattern(pattern.as_list(), 1.0/filling.pattern_scale, -filling.angle) simplified_pattern = [] for angle, base_point, offset, dash_length_items in base_pattern: if len(dash_length_items) > 1: line_pattern = compile_line_pattern(None, dash_length_items) else: line_pattern = CONTINUOUS_PATTERN simplified_pattern.append( HatchPatternLine( angle, base_point, offset, line_pattern, ) ) filling.pattern = simplified_pattern self._hatch_pattern_cache[filling.name] = filling.pattern return filling else: return None
def test_scale_pattern(): p = pattern.load() ansi31 = p["ANSI31"] s = pattern.scale_pattern(ansi31, 2, angle=90) angle, base, offset, lines = s[0] assert angle == 135 assert base == (0, 0) assert offset == (-4.4901280606, -4.4901280606)
def test_scale_pattern(): p = pattern.load(old_pattern=False) ansi31 = p['ANSI31'] s = pattern.scale_pattern(ansi31, 2, angle=90) angle, base, offset, lines = s[0] assert angle == 135 assert base == (0, 0) assert offset == (-4.5254, -4.5254)
def scale(self, factor: float = 1, angle: float = 0) -> None: """Scale and rotate pattern. Be careful, this changes the base pattern definition, maybe better use :meth:`Hatch.set_pattern_scale` or :meth:`Hatch.set_pattern_angle`. Args: factor: scaling factor angle: rotation angle in degrees """ scaled_pattern = pattern.scale_pattern(self.as_list(), factor=factor, angle=angle) self.clear() for line in scaled_pattern: self.add_line(*line)
def setup_pattern(): filling.type = Filling.PATTERN filling.name = hatch.dxf.pattern_name.upper() filling.pattern_scale = hatch.dxf.pattern_scale filling.angle = hatch.dxf.pattern_angle if hatch.dxf.pattern_double: # This value is not editable by CAD-App-GUI: filling.pattern_scale *= 2 # todo: is this correct? filling.pattern = self._hatch_pattern_cache.get(filling.name) if filling.pattern: return pattern = hatch.pattern if not pattern: return # DXF stores the hatch pattern already rotated and scaled, # pattern_scale and pattern_rotation are just hints for the CAD # application to modify the pattern if required. # It's better to revert the scaling and rotation, because in general # back-ends do not handle pattern that way, they need a base-pattern # and separated scaling and rotation attributes and these # base-pattern could be cached by their name. base_pattern = scale_pattern(pattern.as_list(), 1.0 / filling.pattern_scale, -filling.angle) simplified_pattern = [] for angle, base_point, offset, dash_length_items in base_pattern: if len(dash_length_items) > 1: line_pattern = compile_line_pattern( None, dash_length_items) else: line_pattern = CONTINUOUS_PATTERN simplified_pattern.append( HatchPatternLine(angle, base_point, offset, line_pattern)) filling.pattern = simplified_pattern self._hatch_pattern_cache[filling.name] = filling.pattern
def test_rotated_checker(self): pat = pattern.ISO_PATTERN["CHECKER"] result = pattern.PatternAnalyser(pattern.scale_pattern(pat, 2, 45)) assert result.has_angle(45) is True assert result.has_angle(135) is True