def arc(center): center = center arc_start = 150 arc_end = 30 radius = center[2] #p= Path(d=f"M {center[0]} {center[1]}") p = Path(d=[]) current_a = (-(radius * math.cos(math.pi * (arc_start / 180.0))) + center[0], -(radius * math.sin(math.pi * (arc_start / 180.0))) + center[1]) #p.push(f"M {(radius * math.cos(math.pi *arc_start/180.0 )) +center[0] } {(radius * math.sin(math.pi * arc_start/180.0)) +center[1] } ") #p.push(f"M 0 0 L 0 0 {center[0]} {center[1]} ") p.push(f"M {current_a[0]} {current_a[1]} ") target = (-(radius * math.cos(math.pi * (arc_end / 180.1))) + center[0], -(radius * math.sin(math.pi * (arc_end / 180.1))) + center[1]) p.push_arc(target, rotation=0, r=radius, large_arc=False, angle_dir='-', absolute=True) #p.push(f" L {target[0]} {target[1]} ") #p.push(f"L {target[0]} {target[1]} {center[0]} {center[1]}") svg_entity = svgwrite.Drawing().path(d=p.commands, stroke="blue", stroke_width="1", fill="none") ergebnis = svg_entity._repr_svg_() return ergebnis
def test_push_arc_2(self): p = Path('m0,0') p.push_arc(target=(7, 7), rotation=30, r=(2, 4), large_arc=False, angle_dir='-', absolute=True) self.assertEqual(p.tostring(), '<path d="m0,0 A 2 4 30 0,0 7 7" />')
def draw_slice(center, radius, start_angle, stop_angle, **kwargs): p_a = Path(**kwargs) angle = math.radians(stop_angle - start_angle) / 2.0 p_a.push(f"""M {center[0]} {center[1]} l {cos(-1*angle)*radius} {sin(-1*angle)*radius}""") p_a.push_arc( target=(cos(angle) * radius + center[0], sin(angle) * radius + center[1]), rotation=0, r=radius, large_arc=True if stop_angle - start_angle > 180 else False, angle_dir="+", absolute=True, ) p_a.push("Z") p_a.rotate( angle=(min([start_angle, stop_angle]) + (stop_angle - start_angle) / 2.0), center=center, ) return p_a
def trans_arc(dxf_entity): radius= dxf_entity.dxf.radius #stroke = dxf_entity.dxf.color center = slice_l2(dxf_entity.dxf.center) arc_start = dxf_entity.dxf.start_angle arc_end = dxf_entity.dxf.end_angle p=Path(d=[]) radius = dxf_entity.dxf.radius current_a = (-(radius * math.cos(math.pi * (arc_start/180.0 ))) +center[0], -(radius * math.sin(math.pi * (arc_start/180.0))) +center[1]) #p.push(f"M {current_a[0]} {current_a[1]} L {center[0]} {center[1]} {current_a[0]} {current_a[1]} ") p.push(f"M {current_a[0]} {current_a[1]} ") target=( -(radius * math.cos(math.pi * (arc_end/180.1) )) +center[0], -(radius * math.sin(math.pi * (arc_end/180.1)))+center[1] ) p.push_arc(target, rotation=0, r=radius, large_arc=False , angle_dir='-', absolute=True) #p.push(f" L {target[0]} {target[1]} ") #p.push(f"L {target[0]} {target[1]} {center[0]} {center[1]}") #print(f"trans_arc: dxf_entity.dxf.start_angle= {dxf_entity.dxf.start_angle} dxf_entity.dxf.end_angle={dxf_entity.dxf.end_angle} circle_center={circle_center},dxf_entity.dxf.center= {dxf_entity.dxf.center}") #print(f"trans_arc: dxf_entity.dxf.radius= {dxf_entity.dxf.radius}") #svg_entity = svgwrite.Drawing().circle(center=circle_center, r=0, stroke =stroke , fill="none", stroke_width = thickness)# !!! #svg_entity = svgwrite.Drawing().arc(center=circle_center, r=circle_radius, stroke =stroke , fill="none", stroke_width = thickness) svg_entity = svgwrite.Drawing().path(d=p.commands,stroke=stroke, stroke_width=thickness ,fill="none") # ->src/python/svgwrite/svgwrite/path.py print(f"p.commands= {svg_entity._repr_svg_()}") #svg_entity = svgwrite.Drawing().arc(center=circle_center, r=circle_radius, stroke =stroke , fill="none", stroke_width = thickness) svg_entity.scale(SCALE,-SCALE) return svg_entity
def test_push_arc_2(self): p = Path('m0,0') p.push_arc(target=(7,7), rotation=30, r=(2,4), large_arc=False, angle_dir='-', absolute=True) self.assertEqual(p.tostring(), '<path d="m0,0 A 2 4 30 0,0 7 7" />')
def test_push_arc_1(self): p = Path('m0,0') p.push_arc(target=(7,7), rotation=30, r=5) self.assertEqual(p.tostring(), '<path d="m0,0 a 5 5 30 1,1 7 7" />')
class Draw(): def __init__(self, cfg, d=None, svg=None): self.cfg = cfg self.d = d self.svg = svg self.path = None self.materialPath = None self.enable = True self.reverse = False self.last = (0.0, 0.0) self.offset = 0.0 self.pScale = 25.4 * 2 self.xOffset = 50 self.yOffset = 350 self.layerIndex = 0 self.lBorder = BORDER self.lPath = PATH self.lHole = HOLE self.lText = TEXT self.lDebug = DEBUG self.lCount = 0 self.definedLayers = {} self.color = Color.WHITE.value def open(self, inFile, drawDxf=True, drawSvg=True): if drawSvg and self.svg is None: svgFile = inFile + ".svg" try: self.svg = Drawing(svgFile, profile='full', fill='black') self.path = Path(stroke_width=.5, stroke='black', fill='none') except IOError: self.svg = None self.path = None ePrint("svg file open error %s" % (svgFile)) if drawDxf and self.d is None: dxfFile = inFile + "_ngc.dxf" try: self.d = dxf.drawing(dxfFile) self.layerIndex = 0 self.d.add_layer('0', color=self.color, lineweight=0) self.setupLayers() except IOError: self.d = None ePrint("dxf file open error %s" % (dxfFile)) def nextLayer(self): self.layerIndex += 1 self.setupLayers() def setupLayers(self): i = str(self.layerIndex) self.layers = [['lBorder', i + BORDER], \ ['lPath', i + PATH], \ ['lHole', i + HOLE], \ ['lText', i + TEXT], \ ['lDebug', i + DEBUG]] for (var, l) in self.layers: self.definedLayers[l] = True self.d.add_layer(l, color=self.color, lineweight=0) exec("self." + var + "='" + l + "'") def close(self): if self.d is not None: dprt("save drawing file") self.d.save() self.d = None if self.svg is not None: self.svg.add(self.lPath) if self.materialPath is not None: self.svg.add(self.materialPath) self.svg.save() self.svg = None def scaleOffset(self, point): if self.offset == 0.0: point = ((self.xOffset + point[0]) * self.pScale, \ (self.yOffset - point[1]) * self.pScale) else: point = ((self.xOffset + point[0]) * self.pScale, \ (self.yOffset - point[1]) * self.pScale) return point def scale(self, point): point = (point[0] * self.pScale, point[1] * self.pScale) return point def material(self, xSize, ySize): if self.svg is not None: self.offset = 0.0 path = self.materialPath if path is None: self.materialPath = Path(stroke_width=.5, stroke='red', \ fill='none') path = self.materialPath path.push('M', (self.scaleOffset((0, 0)))) path.push('L', (self.scaleOffset((xSize, 0)))) path.push('L', (self.scaleOffset((xSize, ySize)))) path.push('L', (self.scaleOffset((0, ySize)))) path.push('L', (self.scaleOffset((0, 0)))) self.path.push('M', (self.scaleOffset((0, 0)))) # dwg = svgwrite.Drawing(name, (svg_size_width, svg_size_height), \ # debug=True) cfg = self.cfg if self.d is not None: orientation = cfg.orientation if orientation == O_UPPER_LEFT: p0 = (0.0, 0.0) p1 = (xSize, 0.0) p2 = (xSize, -ySize) p3 = (0.0, -ySize) elif orientation == O_LOWER_LEFT: p0 = (0.0, 0.0) p1 = (xSize, 0.0) p2 = (xSize, ySize) p3 = (0.0, ySize) elif orientation == O_UPPER_RIGHT: p0 = (0.0, 0.0) p1 = (-xSize, 0.0) p2 = (-xSize, -ySize) p3 = (0.0, -ySize) elif orientation == O_LOWER_RIGHT: p0 = (0.0, 0.0) p1 = (-xSize, 0.0) p2 = (-xSize, ySize) p3 = (0.0, ySize) elif orientation == O_CENTER: p0 = (-xSize / 2, -ySize / 2) p1 = (xSize / 2, -ySize / 2) p2 = (xSize / 2, ySize / 2) p3 = (-xSize / 2, ySize / 2) elif orientation == O_POINT: dxfInput = cfg.dxfInput p0 = (dxfInput.xMin, dxfInput.yMin) p1 = (dxfInput.xMin, dxfInput.yMax) p2 = (dxfInput.xMax, dxfInput.yMax) p3 = (dxfInput.xMax, dxfInput.yMin) else: ePrint("invalid orientation") self.d.add(dxf.line(p0, p1, layer=self.lBorder)) self.d.add(dxf.line(p1, p2, layer=self.lBorder)) self.d.add(dxf.line(p2, p3, layer=self.lBorder)) self.d.add(dxf.line(p3, p0, layer=self.lBorder)) def materialOutline(self, lines, layer=None): cfg = self.cfg if self.svg is not None: self.xOffset = 0.0 self.yOffset = cfg.dxfInput.ySize self.svg.add(Rect((0, 0), (cfg.dxfInput.xSize * self.pScale, \ cfg.dxfInput.ySize * self.pScale), \ fill='rgb(255, 255, 255)')) path = self.materialPath if path is None: self.materialPath = Path(stroke_width=.5, stroke='red', \ fill='none') path = self.materialPath for l in lines: (start, end) = l path.push('M', (self.scaleOffset(start))) path.push('L', (self.scaleOffset(end))) if self.d is not None: if layer is None: layer = self.lBorder for l in lines: (start, end) = l self.d.add(dxf.line(cfg.dxfInput.fix(start), \ cfg.dxfInput.fix(end), layer=layer)) def move(self, end): if self.enable: if self.svg is not None: self.path.push('M', self.scaleOffset(end)) # dprt("svg move %7.4f %7.4f" % self.scaleOffset(end)) # dprt(" move %7.4f %7.4f" % end) self.last = end def line(self, end, layer=None): if self.enable: if self.svg is not None: self.path.push('L', self.scaleOffset(end)) # dprt("svg line %7.4f %7.4f" % self.scaleOffset(end)) if self.d is not None: if layer is None: layer = self.lPath else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) self.d.add(dxf.line(self.last, end, layer=layer)) # dprt(" line %7.4f %7.4f" % end) self.last = end def arc(self, end, center, layer=None): if self.enable: r = xyDist(end, center) if self.svg is not None: self.path.push_arc(self.scaleOffset(end), 0, r, \ large_arc=True, angle_dir='+', \ absolute=True) if self.d is not None: if layer is None: layer = self.lPath else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) p0 = self.last p1 = end if xyDist(p0, p1) < MIN_DIST: self.d.add(dxf.circle(r, center, layer=layer)) else: # dprt("p0 (%7.4f, %7.4f) p1 (%7.4f, %7.4f)" % \ # (p0[0], p0[1], p1[0], p1[1])) # if orientation(p0, center, p1) == CCW: # (p0, p1) = (p1, p0) a0 = degrees(calcAngle(center, p0)) a1 = degrees(calcAngle(center, p1)) if a1 == 0.0: a1 = 360.0 # dprt("a0 %5.1f a1 %5.1f" % (a0, a1)) self.d.add(dxf.arc(r, center, a0, a1, layer=layer)) self.last = end def circle(self, end, r, layer=None): if self.enable: if self.d is not None: if layer is None: layer = self.lHole else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) self.d.add(dxf.circle(r, end, layer=layer)) self.last = end def hole(self, end, drillSize): if self.enable: if self.svg is not None: self.path.push('L', self.scaleOffset(end)) # dprt("svg line %7.4f %7.4f" % self.scaleOffset(end)) self.svg.add(Circle(self.scaleOffset(end), \ (drillSize / 2) * self.pScale, \ stroke='black', stroke_width=.5, \ fill="none")) if self.d is not None: self.d.add(dxf.line(self.last, end, layer=self.lPath)) self.d.add(dxf.circle(drillSize / 2, end, layer=self.lHole)) self.last = end def text(self, txt, p0, height, layer=None): if self.enable: if self.d is not None: if layer is None: layer = self.lText else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) self.d.add(dxf.text(txt, p0, height, layer=layer)) def add(self, entity): if self.enable: if self.d is not None: self.d.add(entity) def drawCross(self, p, layer=None): if layer is None: layer = self.lDebug else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) (x, y) = p dprt("cross %2d %7.4f, %7.4f" % (self.lCount, x, y)) labelP(p, "%d" % (self.lCount)) last = self.last self.move((x - 0.02, y)) self.line((x + 0.02, y), layer) self.move((x, y - 0.02)) self.line((x, y + 0.02), layer) self.lCount += 1 self.move(last) def drawX(self, p, txt=None, swap=False, layer=None, h=0.010): if layer is None: layer = self.lDebug else: if not layer in self.definedLayers: self.definedLayers[layer] = True self.d.add_layer(layer, color=self.color, lineweight=0) (x, y) = p xOfs = 0.020 yOfs = 0.010 if swap: (xOfs, yOfs) = (yOfs, xOfs) last = self.last self.move((x - xOfs, y - yOfs)) self.line((x + xOfs, y + yOfs), layer) self.move((x - xOfs, y + yOfs)) self.line((x + xOfs, y - yOfs), layer) self.move(p) if txt is not None: self.text('%s' % (txt), (x + xOfs, y - yOfs), h, layer) self.move(last) def drawCircle(self, p, d=0.010, layer=None, txt=None): if layer is None: layer = self.lDebug else: if not layer in self.definedLayers: self.definedLayers[layer] = True if self.d is not None: self.d.add_layer(layer, color=self.color, lineweight=0) last = self.last self.circle(p, d / 2.0, layer) if txt is not None: self.add(dxf.text(txt, p, 0.010, \ alignpoint=p, halign=CENTER, valign=MIDDLE, \ layer=layer)) self.move(last) def drawLine(self, p, m, b, x): self.move(self.offset((0, b), p)) self.move(self.offset((x, m * x + b), p)) def drawLineCircle(self, m, b, r, index): p = (index * 1, 3) self.drawLine(p, m, b, 2 * r) self.hole(offset((0, 0), p), 2 * r)
def species_marker(request, genus_name='-', species_name='-'): """ Generate a SVG marker for a given species Args: request: genus_name: species_name: Returns: """ if species_name == '-': color = 'bbbbbb' species_name = '?' else: color = species_to_color(genus_name, species_name) marker_width = 60 marker_height = 100 marker_border = 5 stroke_width = 1 line_color = 'black' marker_color = '#' + color bezier_length = marker_width / 3 width = marker_width + marker_border * 2 height = marker_height + marker_border * 2 font_size = marker_height / 4 arc_centre_drop = (marker_height / 3.5 ) # Distance from top of marker to rotation centre arc_radius_vertical = arc_centre_drop image = Drawing(size=('%dpx' % width, '%dpx' % height)) marker = Path(stroke=line_color, stroke_width=stroke_width, fill=marker_color) marker.push(f'M {marker_border} {arc_centre_drop + marker_border} ' ) # Left arc edge marker.push( f'C {marker_border} {arc_centre_drop + marker_border + bezier_length} ' f'{width / 2 - bezier_length / 3} {height - marker_border - bezier_length} ' f'{width / 2} {height - marker_border}' # Point ) marker.push( f'C {width / 2 + bezier_length / 3} {height - marker_border - bezier_length} ' f'{width - marker_border} {arc_centre_drop + marker_border + bezier_length} ' f'{width - marker_border} {arc_centre_drop + marker_border} ' # Right edge ) # Right arc edge marker.push_arc(target=(marker_border, arc_centre_drop + marker_border), rotation=180, r=(marker_width / 2, arc_radius_vertical), absolute=True, angle_dir='-') marker.push('z') image.add(marker) image.add( Text(species_name, (width / 2, marker_border + arc_centre_drop + marker_height / 20), font_family='Arial', font_size=font_size, dominant_baseline="middle", text_anchor="middle")) return HttpResponse(image.tostring(), content_type='image/svg+xml')