diff --git a/extensions/fablabchemnitz_elliptical_box.inx b/extensions/fablabchemnitz_elliptical_box.inx deleted file mode 100644 index 2e42203..0000000 --- a/extensions/fablabchemnitz_elliptical_box.inx +++ /dev/null @@ -1,41 +0,0 @@ - - - <_name>Box Maker - Elliptical Box - fablabchemnitz.de.elliptical_box - inkex.py - fablabchemnitz_elliptical_box.py - - <_item value="mm">mm - <_item value="cm">cm - <_item value="m">m - <_item value="km">km - <_item value="in">in - <_item value="ft">ft - <_item value="yd">yd - <_item value="pt">pt - <_item value="px">px - <_item value="pc">pc - - 3.0 - 10.0 - 10.0 - 10.0 - 1.5 - false - 3 - 120 - false - false - false - - all - - - - - - - - diff --git a/extensions/fablabchemnitz_elliptical_box.py b/extensions/fablabchemnitz_elliptical_box.py deleted file mode 100644 index c8130de..0000000 --- a/extensions/fablabchemnitz_elliptical_box.py +++ /dev/null @@ -1,500 +0,0 @@ -#!/usr/bin/env python - -# We will use the inkex module with the predefined Effect base class. -import inkex -# The simplestyle module provides functions for style parsing. - -import simplestyle -from math import * -from collections import namedtuple - -#Note: keep in mind that SVG coordinates start in the top-left corner i.e. with an inverted y-axis - -# first define some SVG primitives (we do not use them all so a cleanup may be in order) -objStyle = simplestyle.formatStyle( - {'stroke': '#000000', - 'stroke-width': 0.28, - 'fill': 'none' - }) - -greenStyle = simplestyle.formatStyle( - {'stroke': '#00ff00', - 'stroke-width': 0.28, - 'fill': 'none' - }) - -def draw_SVG_square((w,h), (x,y), parent): - attribs = { - 'style': objStyle, - 'height': str(h), - 'width': str(w), - 'x': str(x), - 'y': str(y) - } - inkex.etree.SubElement(parent, inkex.addNS('rect', 'svg'), attribs) - -def draw_SVG_ellipse((rx, ry), center, parent, start_end=(0, 2*pi), transform=''): - ell_attribs = {'style': objStyle, - inkex.addNS('cx', 'sodipodi'): str(center.x), - inkex.addNS('cy', 'sodipodi'): str(center.y), - inkex.addNS('rx', 'sodipodi'): str(rx), - inkex.addNS('ry', 'sodipodi'): str(ry), - inkex.addNS('start', 'sodipodi'): str(start_end[0]), - inkex.addNS('end', 'sodipodi'): str(start_end[1]), - inkex.addNS('open', 'sodipodi'): 'true', #all ellipse sectors we will draw are open - inkex.addNS('type', 'sodipodi'): 'arc', - 'transform': transform - } - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), ell_attribs) - - -def draw_SVG_arc((rx, ry), x_axis_rot): - arc_attribs = {'style': objStyle, - 'rx': str(rx), - 'ry': str(ry), - 'x-axis-rotation': str(x_axis_rot), - 'large-arc': '', - 'sweep': '', - 'x': '', - 'y': '' - } - #name='part' - style = {'stroke': '#000000', 'fill': 'none'} - drw = {'style':simplestyle.formatStyle(style),inkex.addNS('label','inkscape'):name,'d':XYstring} - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), drw) - inkex.addNS('', 'svg') - -def draw_SVG_text(coordinate, txt, parent): - text = inkex.etree.Element(inkex.addNS('text', 'svg')) - text.text = txt - text.set('x', str(coordinate.x)) - text.set('y', str(coordinate.y)) - style = {'text-align': 'center', 'text-anchor': 'middle'} - text.set('style', simplestyle.formatStyle(style)) - parent.append(text) - - -def SVG_move_to(x, y): - return "M %d %d" % (x, y) - - -def SVG_line_to(x, y): - return "L %d %d" % (x, y) - - -def SVG_arc_to(rx, ry, x, y): - la = sw = 0 - return "A %d %d 0 %d %d" % (rx, ry, la, sw, x, y) - - -def SVG_path(components): - return '' - -def SVG_curve(parent, segments, style, closed=True): - #pathStr = 'M '+ segments[0] - pathStr = ' '.join(segments) - if closed: - pathStr += ' z' - attributes = { - 'style': style, - 'd': pathStr} - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), attributes) - -#draw an SVG line segment between the given (raw) points -def draw_SVG_line(start, end, parent, style = objStyle): - line_attribs = {'style': style, - 'd': 'M '+str(start.x)+','+str(start.y)+' L '+str(end.x)+','+str(end.y)} - - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) - - -def _makeCurvedSurface(topLeft, w, h, cutSpacing, hCutCount, thickness, parent, invertNotches = False, centralRib = False): - group = inkex.etree.SubElement(parent, 'g') - width = Coordinate(w, 0) - height = Coordinate(0, h) - wCutCount = int(floor(w / cutSpacing)) - if wCutCount % 2 == 0: - wCutCount += 1 # make sure we have an odd number of cuts - xCutDist = w / wCutCount - xSpacing = Coordinate(xCutDist, 0) - ySpacing = Coordinate(0, cutSpacing) - cut = height / hCutCount - ySpacing - plateThickness = Coordinate(0, thickness) - notchEdges = [0] - topHCuts = [] - bottomHCuts = [] - - for cutIndex in range(wCutCount): - if (cutIndex % 2 == 1) != invertNotches: # make a notch here - inset = plateThickness - else: - inset = Coordinate(0, 0) - - # A-column of cuts - aColStart = topLeft + xSpacing * cutIndex - notchEdges.append((aColStart - topLeft).x) - - if cutIndex > 0: # no cuts at x == 0 - draw_SVG_line(aColStart, aColStart + cut / 2, group) - for j in range(hCutCount - 1): - pos = aColStart + cut / 2 + ySpacing + (cut + ySpacing) * j - draw_SVG_line(pos, pos + cut, group) - draw_SVG_line(aColStart + height - cut / 2, aColStart + height, group) - - # B-column of cuts, offset by half the cut length; these cuts run in the opposite direction - bColStart = topLeft + xSpacing * cutIndex + xSpacing / 2 - for j in reversed(range(hCutCount)): - end = bColStart + ySpacing / 2 + (cut + ySpacing) * j - start = end + cut - if centralRib and hCutCount % 2 == 0 and cutIndex % 2 == 1: - holeTopLeft = start + (ySpacing - plateThickness - xSpacing) / 2 - if j == hCutCount // 2 - 1: - start -= plateThickness / 2 - draw_SVG_line(holeTopLeft + plateThickness + xSpacing, holeTopLeft + plateThickness, group) - draw_SVG_line(holeTopLeft, holeTopLeft + xSpacing, group) - elif j == hCutCount // 2: - end += plateThickness / 2 - if j == 0: # first row - end += inset - elif j == hCutCount - 1: # last row - start -= inset - draw_SVG_line(start, end, group) - - #horizontal cuts (should be done last) - topHCuts.append((aColStart + inset, aColStart + inset + xSpacing)) - bottomHCuts.append((aColStart + height - inset, aColStart + height - inset + xSpacing)) - - # draw the outline - for c in reversed(bottomHCuts): - draw_SVG_line(c[1], c[0], group) - draw_SVG_line(topLeft + height, topLeft, group) - for c in topHCuts: - draw_SVG_line(c[0], c[1], group) - draw_SVG_line(topLeft + width, topLeft + width + height, group) - - notchEdges.append(w) - return notchEdges - -def _makeNotchedEllipse(center, ellipse, startAngle, thickness, notches, parent, invertNotches): - startAngle += pi # rotate 180 degrees to put the lid on the topside - c2 = ellipse.notchCoordinate(ellipse.rAngle(startAngle), thickness) - a1 = atan2((ellipse.w/2 + thickness) * c2.y, (ellipse.h/2 + thickness) * c2.x) - for n in range(1, len(notches) - 1): - startA = ellipse.angleFromDist(startAngle, notches[n]) - endA = ellipse.angleFromDist(startAngle, notches[n + 1]) - c1 = center + ellipse.coordinateFromAngle(endA) - c2 = ellipse.notchCoordinate(endA, thickness) - - a2 = atan2((ellipse.w/2 + thickness) * c2.y, (ellipse.h/2 + thickness) * c2.x) - - c2 += center - if (n % 2 == 1) != invertNotches: - draw_SVG_ellipse((ellipse.w / 2, ellipse.h / 2), center, parent, (startA, endA)) - draw_SVG_line(c1, c2, parent) - else: - draw_SVG_ellipse((ellipse.w / 2 + thickness, ellipse.h / 2 + thickness), center, parent, (a1, a2)) - draw_SVG_line(c2, c1, parent) - - a1 = a2 - -class Ellipse(): - nrPoints = 1000 #used for piecewise linear circumference calculation (ellipse circumference is tricky to calculate) - # approximate circumfere: c = pi * (3 * (a + b) - sqrt(10 * a * b + 3 * (a ** 2 + b ** 2))) - - def __init__(self, w, h): - self.h = h - self.w = w - EllipsePoint = namedtuple('EllipsePoint', 'angle coord cDist') - self.ellData = [EllipsePoint(0, Coordinate(w/2, 0), 0)] # (angle, x, y, cumulative distance from angle = 0) - angle = 0 - self.angleStep = 2 * pi / self.nrPoints - #note: the render angle (ra) corresponds to the angle from the ellipse center (ca) according to: - # ca = atan(w/h * tan(ra)) - for i in range(self.nrPoints): - angle += self.angleStep - prev = self.ellData[-1] - x, y = w / 2 * cos(angle), h / 2 * sin(angle) - self.ellData.append(EllipsePoint(angle, Coordinate(x, y), prev.cDist + hypot(prev.coord.x - x, prev.coord.y - y))) - self.circumference = self.ellData[-1].cDist - #inkex.debug("circ: %d" % self.circumference) - - def rAngle(self, a): - """Convert an angle measured from ellipse center to the angle used to generate ellData (used for lookups)""" - cf = 0 - if a > pi / 2: - cf = pi - if a > 3 * pi / 2: - cf = 2 * pi - return atan(self.w / self.h * tan(a)) + cf - - def coordinateFromAngle(self, angle): - """Coordinate of the point at angle.""" - return Coordinate(self.w / 2 * cos(angle), self.h / 2 * sin(angle)) - - def notchCoordinate(self, angle, notchHeight): - """Coordinate for a notch at the given angle. The notch is perpendicular to the ellipse.""" - angle %= (2 * pi) - #some special cases to avoid divide by zero: - if angle == 0: - return (0, Coordinate(self.w / 2 + notchHeight, 0)) - elif angle == pi: - return (pi, Coordinate(-self.w / 2 - notchHeight, 0)) - elif angle == pi / 2: - return(pi / 2, Coordinate(0, self.h / 2 + notchHeight)) - elif angle == 3 * pi / 2: - return(3 * pi / 2, Coordinate(0, -self.h / 2 - notchHeight)) - - x = self.w / 2 * cos(angle) - derivative = self.h / self.w * -x / sqrt((self.w / 2) ** 2 - x ** 2) - if angle > pi: - derivative = -derivative - - normal = -1 / derivative - nAngle = atan(normal) - if angle > pi / 2 and angle < 3 * pi / 2: - nAngle += pi - - nCoordinate = self.coordinateFromAngle(angle) + Coordinate(cos(nAngle), sin(nAngle)) * notchHeight - return nCoordinate - - - def distFromAngles(self, a1, a2): - """Distance accross the surface from point at angle a2 to point at angle a2. Measured in CCW sense.""" - i1 = int(self.rAngle(a1) / self.angleStep) - p1 = self.rAngle(a1) % self.angleStep - l1 = self.ellData[i1 + 1].cDist - self.ellData[i1].cDist - i2 = int(self.rAngle(a2) / self.angleStep) - p2 = self.rAngle(a2) % self.angleStep - l2 = self.ellData[i2 + 1].cDist - self.ellData[i2].cDist - if a1 <= a2: - len = self.ellData[i2].cDist - self.ellData[i1].cDist + l2 * p2 - l1 * p1 - else: - len = self.circumference + self.ellData[i2].cDist - self.ellData[i1].cDist - return len - - def angleFromDist(self, startAngle, relDist): - """Returns the angle that you get when starting at startAngle and moving a distance (dist) in CCW direction""" - si = int(self.rAngle(startAngle) / self.angleStep) - p = self.rAngle(startAngle) % self.angleStep - - l = self.ellData[si + 1].cDist - self.ellData[si].cDist - - startDist = self.ellData[si].cDist + p * l - - absDist = relDist + startDist - - if absDist > self.ellData[-1].cDist: # wrap around zero angle - absDist -= self.ellData[-1].cDist - - iMin = 0 - iMax = self.nrPoints - count = 0 - while iMax - iMin > 1: # binary search - count += 1 - iHalf = iMin + (iMax - iMin) // 2 - if self.ellData[iHalf].cDist < absDist: - iMin = iHalf - else: - iMax = iHalf - - stepDist = self.ellData[iMax].cDist - self.ellData[iMin].cDist - return self.ellData[iMin].angle + self.angleStep * (absDist - self.ellData[iMin].cDist)/stepDist - - -class Coordinate: - def __init__(self, x, y): - self.x = x - self.y = y - - def __add__(self, other): - return Coordinate(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return Coordinate(self.x - other.x, self.y - other.y) - - def __mul__(self, factor): - return Coordinate(self.x * factor, self.y * factor) - - def __div__(self, quotient): - return Coordinate(self.x / quotient, self.y / quotient) - - -class EllipticalBox(inkex.Effect): - """ - Creates a new layer with the drawings for a parametrically generaded box. - """ - def __init__(self): - inkex.Effect.__init__(self) - self.knownUnits = ['in', 'pt', 'px', 'mm', 'cm', 'm', 'km', 'pc', 'yd', 'ft'] - - self.OptionParser.add_option('-u', '--unit', action = 'store', - type = 'string', dest = 'unit', default = 'mm', - help = 'Unit, should be one of ') - - self.OptionParser.add_option('-t', '--thickness', action = 'store', - type = 'float', dest = 'thickness', default = '3.0', - help = 'Material thickness') - - self.OptionParser.add_option('-x', '--width', action = 'store', - type = 'float', dest = 'width', default = '3.0', - help = 'Box width') - - self.OptionParser.add_option('-z', '--height', action = 'store', - type = 'float', dest = 'height', default = '10.0', - help = 'Box height') - - self.OptionParser.add_option('-y', '--depth', action = 'store', - type = 'float', dest = 'depth', default = '3.0', - help = 'Box depth') - - self.OptionParser.add_option('-d', '--cut_dist', action = 'store', - type = 'float', dest = 'cut_dist', default = '1.5', - help = 'Distance between cuts on the wrap around. Note that this value will change slightly to evenly fill up the available space.') - - self.OptionParser.add_option('--auto_cut_dist', action = 'store', - type = 'inkbool', dest = 'auto_cut_dist', default = 'false', - help = 'Automatically set the cut distance based on the curvature.') - - self.OptionParser.add_option('-c', '--cut_nr', action = 'store', - type = 'int', dest = 'cut_nr', default = '3', - help = 'Number of cuts across the depth of the box.') - - self.OptionParser.add_option('-a', '--lid_angle', action = 'store', - type = 'float', dest = 'lid_angle', default = '120', - help = 'Angle that forms the lid (in degrees, measured from centerpoint of the ellipse)') - - self.OptionParser.add_option('-b', '--body_ribcount', action = 'store', - type = 'int', dest = 'body_ribcount', default = '0', - help = 'Number of ribs in the body') - - self.OptionParser.add_option('-l', '--lid_ribcount', action = 'store', - type = 'int', dest = 'lid_ribcount', default = '0', - help = 'Number of ribs in the lid') - - self.OptionParser.add_option('-n', '--invert_lid_notches', action = 'store', - type = 'inkbool', dest = 'invert_lid_notches', default = 'false', - help = 'Invert the notch pattern on the lid (to prevent sideways motion)') - - self.OptionParser.add_option('-r', '--central_rib_lid', action = 'store', - type = 'inkbool', dest = 'centralRibLid', default = 'false', - help = 'Create a central rib in the lid') - - self.OptionParser.add_option('-R', '--central_rib_body', action = 'store', - type = 'inkbool', dest = 'centralRibBody', default = 'false', - help = 'Create a central rib in the body') - - try: - inkex.Effect.unittouu # unitouu has moved since Inkscape 0.91 - except AttributeError: - try: - def unittouu(self, unit): - return inkex.unittouu(unit) - except AttributeError: - pass - - def effect(self): - """ - Draws as basic elliptical box, based on provided parameters - """ - - # input sanity check - error = False - if min(self.options.height, self.options.width, self.options.depth) == 0: - inkex.errormsg('Error: Dimensions must be non zero') - error = True - - if self.options.cut_nr < 1: - inkex.errormsg('Error: Number of cuts should be at least 1') - error = True - - if (self.options.centralRibLid or self.options.centralRibBody) and self.options.cut_nr % 2 == 1: - inkex.errormsg('Error: Central rib is only valid with an even number of cuts') - error = True - - if self.options.unit not in self.knownUnits: - inkex.errormsg('Error: unknown unit. '+ self.options.unit) - error = True - - if error: - exit() - - - # convert units - unit = self.options.unit - H = self.unittouu(str(self.options.height) + unit) - W = self.unittouu(str(self.options.width) + unit) - D = self.unittouu(str(self.options.depth) + unit) - thickness = self.unittouu(str(self.options.thickness) + unit) - cutSpacing = self.unittouu(str(self.options.cut_dist) + unit) - cutNr = self.options.cut_nr - - svg = self.document.getroot() - docWidth = self.unittouu(svg.get('width')) - docHeigh = self.unittouu(svg.attrib['height']) - - layer = inkex.etree.SubElement(svg, 'g') - layer.set(inkex.addNS('label', 'inkscape'), 'Elliptical Box') - layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') - - ell = Ellipse(W, H) - - #body and lid - lidAngleRad = self.options.lid_angle * 2 * pi / 360 - lidStartAngle = pi / 2 - lidAngleRad / 2 - lidEndAngle = pi / 2 + lidAngleRad / 2 - - lidLength = ell.distFromAngles(lidStartAngle, lidEndAngle) - bodyLength = ell.distFromAngles(lidEndAngle, lidStartAngle) - - # do not put elements right at the edge of the page - xMargin = 3 - yMargin = 3 - bodyNotches = _makeCurvedSurface(Coordinate(xMargin, yMargin), bodyLength, D, cutSpacing, cutNr, thickness, layer, False, self.options.centralRibBody) - lidNotches = _makeCurvedSurface(Coordinate(xMargin, D + 2 * yMargin), lidLength, D, cutSpacing, cutNr, thickness, layer, not self.options.invert_lid_notches, self.options.centralRibLid) - a1 = lidEndAngle - - # create elliptical sides - sidesGrp = inkex.etree.SubElement(layer, 'g') - - elCenter = Coordinate(xMargin + thickness + W / 2, 2 * D + H / 2 + thickness + 3 * yMargin) - - # indicate the division between body and lid - if self.options.invert_lid_notches: - draw_SVG_line(elCenter, elCenter + ell.coordinateFromAngle(ell.rAngle(lidStartAngle + pi)), sidesGrp, greenStyle) - draw_SVG_line(elCenter, elCenter + ell.coordinateFromAngle(ell.rAngle(lidEndAngle + pi)), sidesGrp, greenStyle) - else: - angleA = ell.angleFromDist(lidStartAngle, lidNotches[2]) - angleB = ell.angleFromDist(lidStartAngle, lidNotches[-2]) - - draw_SVG_line(elCenter, elCenter + ell.coordinateFromAngle(angleA + pi), sidesGrp, greenStyle) - draw_SVG_line(elCenter, elCenter + ell.coordinateFromAngle(angleB + pi), sidesGrp, greenStyle) - - _makeNotchedEllipse(elCenter, ell, lidEndAngle, thickness, bodyNotches, sidesGrp, False) - _makeNotchedEllipse(elCenter, ell, lidStartAngle, thickness, lidNotches, sidesGrp, not self.options.invert_lid_notches) - - # ribs - spacer = Coordinate(0, 10) - innerRibCenter = Coordinate(xMargin + thickness + W / 2, 2 * D + 1.5 * (H + 2 *thickness) + 4 * yMargin) - innerRibGrp = inkex.etree.SubElement(layer, 'g') - - outerRibCenter = Coordinate(2 * xMargin + 1.5 * (W + 2 * thickness) , 2 * D + 1.5 * (H + 2 * thickness) + 4 * yMargin) - outerRibGrp = inkex.etree.SubElement(layer, 'g') - - - if self.options.centralRibLid: - - _makeNotchedEllipse(innerRibCenter, ell, lidStartAngle, thickness, lidNotches, innerRibGrp, False) - _makeNotchedEllipse(outerRibCenter, ell, lidStartAngle, thickness, lidNotches, outerRibGrp, True) - - if self.options.centralRibBody: - _makeNotchedEllipse(innerRibCenter + spacer, ell, lidEndAngle, thickness, bodyNotches, innerRibGrp, False) - _makeNotchedEllipse(outerRibCenter + spacer, ell, lidEndAngle, thickness, bodyNotches, outerRibGrp, True) - - if self.options.centralRibLid or self.options.centralRibBody: - draw_SVG_text(elCenter, 'side (duplicate this)', sidesGrp) - draw_SVG_text(innerRibCenter, 'inside rib', innerRibGrp) - draw_SVG_text(outerRibCenter, 'outside rib', outerRibGrp) - -# Create effect instance and apply it. -effect = EllipticalBox() -effect.affect() diff --git a/extensions/fablabchemnitz_encoder_disk_generator.inx b/extensions/fablabchemnitz_encoder_disk_generator.inx deleted file mode 100644 index 9a90cb3..0000000 --- a/extensions/fablabchemnitz_encoder_disk_generator.inx +++ /dev/null @@ -1,81 +0,0 @@ - - - <_name>Encoder Disk Generator -fablabchemnitz.de.encoder_disk_generator -inkex.py -fablabchemnitz_encoder_disk_generator.py - - - 0.0 - 0.0 - 1 - 0.0 - 0.0 - 0.0 - 0.0 - - - 0.0 - 0.0 - 1 - 0.0 - 0.0 - 0.0 - - - 0.0 - 0.0 - 1 - 1 - 0.0 - 0.0 - - - 30.0 - 5.0 - 010011110111000010001101 - 25.0 - 10.0 - - - - all - - - - - - - - diff --git a/extensions/fablabchemnitz_encoder_disk_generator.py b/extensions/fablabchemnitz_encoder_disk_generator.py deleted file mode 100644 index 1cc40ef..0000000 --- a/extensions/fablabchemnitz_encoder_disk_generator.py +++ /dev/null @@ -1,487 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import inkex -import simplestyle -import math -import string -import simpletransform - - -# Function for calculating a point from the origin when you know the distance -# and the angle -def calculatePoint(angle, distance): - if (angle < 0 or angle > 360): - return None - else: - return [ - distance * math.cos(math.radians(angle)), - distance * math.sin(math.radians(angle))] - - -class EncoderDiskGenerator(inkex.Effect): - - def __init__(self): - inkex.Effect.__init__(self) - self.OptionParser.add_option("--tab", - action="store", type="string", - dest="tab", default="rotary_enc", - help="Selected tab") - self.OptionParser.add_option("--diameter", - action="store", type="float", - dest="diameter", default=0.0, - help="Diameter of the encoder disk") - self.OptionParser.add_option("--hole_diameter", - action="store", type="float", - dest="hole_diameter", default=0.0, - help="Diameter of the center hole") - self.OptionParser.add_option("--segments", - action="store", type="int", - dest="segments", default=0, - help="Number of segments") - self.OptionParser.add_option("--outer_encoder_diameter", - action="store", type="float", - dest="outer_encoder_diameter", default=0.0, - help="Diameter of the outer encoder disk") - self.OptionParser.add_option("--outer_encoder_width", - action="store", type="float", - dest="outer_encoder_width", default=0.0, - help="Width of the outer encoder disk") - self.OptionParser.add_option("--inner_encoder_diameter", - action="store", type="float", - dest="inner_encoder_diameter", default=0.0, - help="Diameter of the inner encoder disk") - self.OptionParser.add_option("--inner_encoder_width", - action="store", type="float", - dest="inner_encoder_width", default=0.0, - help="Width of the inner encoder disk") - self.OptionParser.add_option("--bits", - action="store", type="int", - dest="bits", default=1, - help="Number of bits/tracks") - self.OptionParser.add_option("--encoder_diameter", - action="store", type="float", - dest="encoder_diameter", default=0.0, - help="Outer diameter of the last track") - self.OptionParser.add_option("--track_width", - action="store", type="float", - dest="track_width", default=0.0, - help="Width of one track") - self.OptionParser.add_option("--track_distance", - action="store", type="float", - dest="track_distance", default=0.0, - help="Distance between tracks") - self.OptionParser.add_option("--bm_diameter", - action="store", type="float", - dest="bm_diameter", default=0.0, - help="Diameter of the encoder disk") - self.OptionParser.add_option("--bm_hole_diameter", - action="store", type="float", - dest="bm_hole_diameter", default=0.0, - help="Diameter of the center hole") - self.OptionParser.add_option("--bm_bits", - action="store", type="string", - dest="bm_bits", default="", - help="Bits of segments") - self.OptionParser.add_option("--bm_outer_encoder_diameter", - action="store", type="float", - dest="bm_outer_encoder_diameter", default=0.0, - help="Diameter of the outer encoder disk") - self.OptionParser.add_option("--bm_outer_encoder_width", - action="store", type="float", - dest="bm_outer_encoder_width", default=0.0, - help="Width of the outer encoder disk") - self.OptionParser.add_option("--brgc_diameter", - action="store", type="float", - dest="brgc_diameter", default=0.0, - help="Diameter of the encoder disk") - self.OptionParser.add_option("--stgc_diameter", - action="store", type="float", - dest="stgc_diameter", default=0.0, - help="Diameter of the encoder disk") - self.OptionParser.add_option("--brgc_hole_diameter", - action="store", type="float", - dest="brgc_hole_diameter", default=0.0, - help="Diameter of the center hole") - self.OptionParser.add_option("--cutouts", - action="store", type="int", - dest="cutouts", default=1, - help="Number of cutouts") - self.OptionParser.add_option("--sensors", - action="store", type="int", - dest="sensors", default=1, - help="Number of sensors") - self.OptionParser.add_option("--stgc_hole_diameter", - action="store", type="float", - dest="stgc_hole_diameter", default=0.0, - help="Diameter of the center hole") - self.OptionParser.add_option("--stgc_encoder_diameter", - action="store", type="float", - dest="stgc_encoder_diameter", default=0.0, - help="Outer diameter of the last track") - self.OptionParser.add_option("--stgc_track_width", - action="store", type="float", - dest="stgc_track_width", default=0.0, - help="Width of track") - - # This function just concatenates the point and the command and returns - # the data string - def parsePathData(self, command, point): - - path_data = command + ' %f ' % point[0] + ' %f ' % point[1] - return path_data - - # Creates a gray code of size bits (n >= 1) in the format of a list - def createGrayCode(self, bits): - - gray_code = [[False], [True]] - - if bits == 1: - return gray_code - - for i in range(bits - 1): - temp = [] - # Reflect values - for j in range(len(gray_code[0]), 0, -1): - for k in range(0, len(gray_code)): - if j == len(gray_code[0]): - temp.append([gray_code[k][-j]]) - else: - temp[k].append(gray_code[k][-j]) - while temp: - gray_code.append(temp.pop()) - # Add False to the "old" values and true to the new ones - for j in range(0, len(gray_code)): - if j < len(gray_code) / 2: - gray_code[j].insert(0, False) - else: - gray_code[j].insert(0, True) - temp = [] - - return gray_code - - # This function returns the segments for a gray encoder - def drawGrayEncoder(self, line_style, bits, encoder_diameter, track_width, - track_distance): - gray_code = self.createGrayCode(bits) - - segments = [] - segment_size = 0 - start_angle_position = 0 - index = 0 - current_encoder_diameter = encoder_diameter - previous_item = False - position_size = 360.0 / (2 ** bits) - - for i in range(len(gray_code[0]) - 1, -1, -1): - for j in gray_code: - if j[i]: - segment_size += 1 - if segment_size == 1: - start_angle_position = index - previous_item = True - elif not j[i] and previous_item: - segments.append( - self.drawSegment(line_style, - start_angle_position * position_size, - segment_size * position_size, - current_encoder_diameter, - track_width)) - - segment_size = 0 - previous_item = False - start_angle_position = 0 - - index += 1 - - if previous_item: - segments.append(self.drawSegment(line_style, - start_angle_position * position_size, - segment_size * position_size, - current_encoder_diameter, track_width)) - segment_size = 0 - previous_item = False - start_angle_position = 0 - current_encoder_diameter -= (2 * track_distance + 2 * track_width) - index = 0 - - return segments - - # Check if there is too many cutouts compared to number of sensors - def validSTGrayEncoder(self, cutouts, sensors): - if sensors < 6 and cutouts > 1: - pass - elif sensors <= 10 and cutouts > 2: - pass - elif sensors <= 16 and cutouts > 3: - pass - elif sensors <= 23 and cutouts > 4: - pass - elif sensors <= 36 and cutouts > 5: - pass - else: - return True - - return False - - # This function returns the segments for a single-track gray encoder - def drawSTGrayEncoder( - self, line_style, cutouts, sensors, encoder_diameter, track_width): - - segments = [] - resolution = 360.0 / (cutouts * 2 * sensors) - current_angle = 0.0 - added_angle = ((2 * cutouts + 1) * resolution) - for n in range(cutouts): - current_segment_size = ((n * 2 + 2) * cutouts + 1) * resolution - segments.append( - self.drawSegment( - line_style, current_angle, - current_segment_size, - encoder_diameter, track_width)) - current_angle += added_angle + current_segment_size - - return segments - - def drawLabel(self, group, angle, segment_angle, outer_diameter, labelNum): - outer_radius = outer_diameter / 2 - label_angle = angle + (segment_angle / 2) - point = calculatePoint(label_angle, outer_radius) - matrix = simpletransform.parseTransform( - 'rotate(' + str(label_angle + 90) + ')') - matrix_str = str(matrix[0][0]) + "," + str(matrix[0][1]) - matrix_str += "," + str(matrix[1][0]) + "," + str(matrix[1][1]) + ",0,0" - text = { - 'id': 'text' + str(labelNum), - #'sodipodi:linespacing': '0%', - 'style': 'font-size: 6px;font-style: normal;font-family: Sans', - #'transform': 'matrix(' + matrix_str + ')', - 'x': str(point[0]), - 'y': str(point[1]), - #'xml:space': 'preserve' - } - textElement = inkex.etree.SubElement(group, inkex.addNS('text', 'svg'), text) - #tspanElement = inkex.etree.Element( - # textElement, '{%s}%s' % (svg_uri, 'tspan'), tspan) - textElement.text = string.printable[labelNum % len(string.printable)] - - self.current_layer.append(textElement) - - # This function creates the path for one single segment - def drawSegment(self, line_style, angle, segment_angle, outer_diameter, width): - - path = {'style': simplestyle.formatStyle(line_style)} - path['d'] = '' - outer_radius = outer_diameter / 2 - - # Go to the first point in the segment - path['d'] += self.parsePathData( - 'M', calculatePoint(angle, outer_radius - width)) - - # Go to the second point in the segment - path['d'] += self.parsePathData('L', calculatePoint(angle, outer_radius)) - - # Go to the third point in the segment, draw an arc - point = calculatePoint(angle + segment_angle, outer_radius) - path['d'] += self.parsePathData('A', [outer_radius, outer_radius]) + \ - '0 0 1' + self.parsePathData(' ', point) - - # Go to the fourth point in the segment - point = calculatePoint(angle + segment_angle, outer_radius - width) - path['d'] += self.parsePathData('L', point) - - # Go to the beginning in the segment, draw an arc - point = calculatePoint(angle, outer_radius - width) - # 'Z' closes the path - path['d'] += (self.parsePathData( - 'A', - [outer_radius - width, outer_radius - width]) + - '0 0 0' + self.parsePathData(' ', point) + ' Z') - - # Return the path - return path - - # This function adds an element to the document - def addElement(self, element_type, group, element_attributes): - inkex.etree.SubElement( - group, inkex.addNS(element_type, 'svg'), - element_attributes) - - def drawCircles(self, hole_diameter, diameter): - # Attributes for the center hole, then create it, if diameter is 0, dont - # create it - circle_elements = [] - attributes = { - 'style': simplestyle.formatStyle({'stroke': 'none', 'fill': 'black'}), - 'r': str(hole_diameter / 2) - } - if self.options.hole_diameter > 0: - circle_elements.append(attributes) - - # Attributes for the guide hole in the center hole, then create it - attributes = { - 'style': simplestyle.formatStyle( - {'stroke': 'white', 'fill': 'white', 'stroke-width': '0.1'}), - 'r': '1' - } - circle_elements.append(attributes) - - # Attributes for the outer rim, then create it - attributes = { - 'style': simplestyle.formatStyle( - {'stroke': 'black', 'stroke-width': '1', 'fill': 'none'}), - 'r': str(diameter / 2) - } - if self.options.diameter > 0: - circle_elements.append(attributes) - - return circle_elements - - def drawCommonCircles(self, group, diameter, hole_diameter): - circle_elements = self.drawCircles(hole_diameter, diameter) - - for circle in circle_elements: - self.addElement('circle', group, circle) - - def effectBrgc(self, group, line_style, diameter, hole_diameter): - - if (((self.options.encoder_diameter / 2) - - (self.options.bits * self.options.track_width + - (self.options.bits - 1) * self.options.track_distance)) < - self.options.brgc_hole_diameter / 2): - inkex.errormsg("Innermost encoder smaller than the center hole!") - else: - segments = self.drawGrayEncoder( - line_style, self.options.bits, - self.options.encoder_diameter, - self.options.track_width, - self.options.track_distance) - for item in segments: - self.addElement('path', group, item) - - self.drawCommonCircles(group, diameter, hole_diameter) - - def effectStgc(self, group, line_style, diameter, hole_diameter): - - if ((self.options.stgc_encoder_diameter / 2) - - self.options.stgc_track_width < self.options.stgc_hole_diameter / 2): - inkex.errormsg("Encoder smaller than the center hole!") - elif not self.validSTGrayEncoder(self.options.cutouts, self.options.sensors): - inkex.errormsg("Too many cutouts compared to number of sensors!") - else: - segments = self.drawSTGrayEncoder(line_style, self.options.cutouts, - self.options.sensors, self.options.stgc_encoder_diameter, - self.options.stgc_track_width) - for item in segments: - self.addElement('path', group, item) - - self.drawCommonCircles(group, diameter, hole_diameter) - - def effectRotaryEnc(self, group, line_style, diameter, hole_diameter): - - # Angle of one single segment - segment_angle = 360.0 / (self.options.segments * 2) - - for segment_number in range(0, self.options.segments): - - angle = segment_number * (segment_angle * 2) - - if (self.options.outer_encoder_width > 0 and - self.options.outer_encoder_diameter > 0 and - self.options.outer_encoder_diameter / 2 > - self.options.outer_encoder_width): - - segment = self.drawSegment(line_style, angle, - segment_angle, - self.options.outer_encoder_diameter, - self.options.outer_encoder_width) - self.addElement('path', group, segment) - - # If the inner encoder diameter is something else than 0; create it - if (self.options.outer_encoder_width > 0 and - self.options.inner_encoder_diameter > 0 and - self.options.inner_encoder_diameter / 2 > - self.options.inner_encoder_width): - - # The inner encoder must be half an encoder segment ahead of the outer one - segment = self.drawSegment( - line_style, angle + (segment_angle / 2), segment_angle, - self.options.inner_encoder_diameter, - self.options.inner_encoder_width) - - self.addElement('path', group, segment) - - self.drawCommonCircles(group, diameter, hole_diameter) - - def effectBitmapEnc(self, group, line_style, diameter, hole_diameter): - - bits = self.options.bm_bits - bm_segments = len(bits) - # Angle of one single segment - segment_angle = 360.0 / bm_segments - - for segment_number in range(0, bm_segments): - - angle = segment_number * segment_angle - - if (self.options.bm_outer_encoder_width > 0 and - self.options.bm_outer_encoder_diameter > 0 and - self.options.bm_outer_encoder_diameter > - self.options.bm_outer_encoder_width): - - self.drawLabel(group, - angle, segment_angle, - self.options.bm_diameter, - segment_number) - # Drawing only the black segments - if (bits[segment_number] == '1'): - segment = self.drawSegment( - line_style, angle, - segment_angle, - self.options.bm_outer_encoder_diameter, - self.options.bm_outer_encoder_width) - - self.addElement('path', group, segment) - - self.drawCommonCircles(group, diameter, hole_diameter) - - def effect(self): - - # Group to put all the elements in, center set in the middle of the view - group = inkex.etree.SubElement(self.current_layer, 'g', { - inkex.addNS('label', 'inkscape'): 'Encoder disk', - 'transform': 'translate' + str(self.view_center) - }) - - # Line style for the encoder segments - line_style = { - 'stroke': 'white', - 'stroke-width': '0', - 'fill': 'black' - } - - if self.options.tab == "\"brgc\"": - self.effectBrgc(group, line_style, - self.options.brgc_diameter, - self.options.brgc_hole_diameter) - - if self.options.tab == "\"stgc\"": - self.effectStgc(group, line_style, - self.options.stgc_diameter, - self.options.stgc_hole_diameter) - - if self.options.tab == "\"rotary_enc\"": - self.effectRotaryEnc(group, line_style, - self.options.diameter, - self.options.hole_diameter) - - if self.options.tab == "\"bitmap_enc\"": - self.effectBitmapEnc(group, line_style, - self.options.bm_diameter, - self.options.bm_hole_diameter) - - -if __name__ == '__main__': - # Run the effect - effect = EncoderDiskGenerator() - effect.affect() diff --git a/extensions/fablabchemnitz_fill_row.inx b/extensions/fablabchemnitz_fill_row.inx deleted file mode 100644 index 3d8a984..0000000 --- a/extensions/fablabchemnitz_fill_row.inx +++ /dev/null @@ -1,25 +0,0 @@ - - - - <_name>Fill With Copies - fablabchemnitz.de.fill_row - - inkex.py - fablabchemnitz_fill_row.py - - Fills a row with seleted object. Author: Pawel Mosakowski - - - all - - - - - - - - - - diff --git a/extensions/fablabchemnitz_fill_row.py b/extensions/fablabchemnitz_fill_row.py deleted file mode 100644 index 99b48e3..0000000 --- a/extensions/fablabchemnitz_fill_row.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python2 - -import sys -sys.path.append('/usr/share/inkscape/extensions') - -from inkex import Effect as InkscapeEffect -from inkex import etree, addNS - -from copy import deepcopy - -from simpletransform import computeBBox, applyTransformToNode -from simplepath import parsePath, translatePath, formatPath - -class FillRow(InkscapeEffect): - def __init__(self): - InkscapeEffect.__init__(self) - self.filename = sys.argv[-1] - - def effect(self): - if len(self.selected) > 0: - # bboxes = self.calculate_bboxes(self.selected) - self.total_height = 0 - for id, node in self.selected.items(): - self.fill_row(node) - - def fill_row(self, node): - max_line_width = self.unittouu('450mm') - - x_gap = y_gap = self.unittouu('10mm') - x_start = self.unittouu('3mm') - y_start = self.unittouu('1600mm') - self.unittouu('3mm') - - total_width = 0 - total_height = self.total_height - - group = etree.SubElement(self.current_layer, addNS('g','svg')) - - bbox = computeBBox([node]) - x, _, y, _ = bbox - node_width = x_gap + self.width(bbox) - - while total_width + node_width < max_line_width: - node_copy = deepcopy(node) - group.append(node_copy) - - x_dest = x_start + total_width - y_dest = y_start - (total_height + self.height(bbox)) - - # translation logic - if node_copy.tag == addNS('path','svg'): - x_delta = x_dest - x - y_delta = y_dest - y - - path = parsePath(node_copy.attrib['d']) - translatePath(path, x_delta, y_delta) - node_copy.attrib['d'] = formatPath(path) - elif node_copy.tag == addNS('g','svg'): - x_delta = x_dest - x - y_delta = y_dest - y - - translation_matrix = [[1.0, 0.0, x_delta], [0.0, 1.0, y_delta]] - applyTransformToNode(translation_matrix, node_copy) - - else: - node_copy.attrib['x'] = str(x_dest) - node_copy.attrib['y'] = str(y_dest) - - total_width += node_width - - self.total_height += self.height(computeBBox(group)) + y_gap - - def width(self,bbox): - (x1, x2, y1, y2) = bbox - width = x2 - x1 - - return width - - def height(self,bbox): - (x1, x2, y1, y2) = bbox - height = y2 - y1 - - return height - - -effect = FillRow() -effect.affect() diff --git a/extensions/fablabchemnitz_netting.inx b/extensions/fablabchemnitz_netting.inx deleted file mode 100644 index 15c4f47..0000000 --- a/extensions/fablabchemnitz_netting.inx +++ /dev/null @@ -1,20 +0,0 @@ - - - <_name>Netting - fablabchemnitz.de.netting - fablabchemnitz_netting.py - inkex.py - <_param name="title" type="description">This effect net in the a path alternately. - 1.0 - - path - - - - - - - - \ No newline at end of file diff --git a/extensions/fablabchemnitz_netting.py b/extensions/fablabchemnitz_netting.py deleted file mode 100644 index 9198d79..0000000 --- a/extensions/fablabchemnitz_netting.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -''' -netting.py -Sunabe kazumichi 2010/3/4 -http://dp48069596.lolipop.jp/ - - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -this program nets in the line. -''' -import random, math, inkex, simplestyle, cubicsuperpath - - -class RadiusRandomize(inkex.Effect): - def __init__(self): - inkex.Effect.__init__(self) - self.OptionParser.add_option("-w", "--s_width", - action="store", type="float", - dest="s_width", default=1.0, - help="atrke width") - self.OptionParser.add_option("--title") - - def effect(self): - path_strings = [] - net_strings= ["M"] - my_path = inkex.etree.Element(inkex.addNS('path','svg')) - s = {'stroke-width': self.options.s_width, 'stroke': '#000000', 'fill': 'none' } - my_path.set('style', simplestyle.formatStyle(s)) - for id, node in self.selected.iteritems(): - if node.tag == inkex.addNS('path','svg'): - d = node.get('d') - p = cubicsuperpath.parsePath(d) - for subpath in p: - for i, csp in enumerate(subpath): - path_strings.append("%f,%f" % ( csp[1][0], csp[1][1])) - node.set('d',cubicsuperpath.formatPath(p)) - - while len(path_strings)>0 : - net_strings.append(path_strings.pop(0)) - if len(path_strings)>0 : - net_strings.append(path_strings.pop()) - my_path.set('d', " ".join(net_strings)) - self.current_layer.append( my_path ) - - - - -e = RadiusRandomize() -e.affect() - diff --git a/extensions/fablabchemnitz_scatter.inx b/extensions/fablabchemnitz_scatter.inx deleted file mode 100644 index c74f8e3..0000000 --- a/extensions/fablabchemnitz_scatter.inx +++ /dev/null @@ -1,24 +0,0 @@ - - - <_name>Scatter 2 - fablabchemnitz.de.scatter2 - pathmodifier.py - fablabchemnitz_scatter.py - inkex.py - This effect scatters pattern objects randomly around segment points of arbitrary "skeleton" paths. The pattern is the top most object in the selection. Random_off:density=1,offset=0 - true - 6 - 3 - 20.0 - 20.0 - - - - - - - - - \ No newline at end of file diff --git a/extensions/fablabchemnitz_scatter.py b/extensions/fablabchemnitz_scatter.py deleted file mode 100644 index c87ab6c..0000000 --- a/extensions/fablabchemnitz_scatter.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python -''' -scatter.py -Sunabe kazumichi 2009/9/29 -http://dp48069596.lolipop.jp/ - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -attention:when rotation degree become large, patterns are deformed largely. -therefore,restricted the rotation in range -30 - - <_name>Parametric Shelves - fablabchemnitz.de.shelves - inkex.py - fablabchemnitz_shelves.py - - <_item value="mm">mm - <_item value="cm">cm - <_item value="m">m - <_item value="km">km - <_item value="in">in - <_item value="ft">ft - <_item value="yd">yd - <_item value="pt">pt - <_item value="px">px - <_item value="pc">pc - - 1.2 - 0.3 - 0.05 - 100 - 100 - 40 - 10; 20; 35 - 0.6 - 10 - - all - - - - - - - - \ No newline at end of file diff --git a/extensions/fablabchemnitz_shelves.py b/extensions/fablabchemnitz_shelves.py deleted file mode 100644 index 4e30ccd..0000000 --- a/extensions/fablabchemnitz_shelves.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python - -#import Inkscape_helper.inkscape_helper as helper -import fablabchemnitz_shelves_helper as doc - -#import simplestyle - - -#Note: keep in mind that SVG coordinates start in the top-left corner i.e. with an inverted y-axis - - -class Shelves(doc.Effect): - """ - Creates a new layer with the drawings for a parametrically generaded box. - """ - def __init__(self): - doc.Effect.__init__(self) - - self.OptionParser.add_option('--unit', action = 'store', - type = 'string', dest = 'unit', default = 'cm', - help = 'Unit, should be one of ') - - self.OptionParser.add_option('--tool_diameter', action = 'store', - type = 'float', dest = 'tool_diameter', default = '0.3', - help = 'Tool diameter') - - self.OptionParser.add_option('--tolerance', action = 'store', - type = 'float', dest = 'tolerance', default = '0.05', - help = '') - - self.OptionParser.add_option('--thickness', action = 'store', - type = 'float', dest = 'thickness', default = '1.2', - help = 'Material thickness') - - self.OptionParser.add_option('--width', action = 'store', - type = 'float', dest = 'width', default = '3.0', - help = 'Box width') - - self.OptionParser.add_option('--height', action = 'store', - type = 'float', dest = 'height', default = '10.0', - help = 'Box height') - - self.OptionParser.add_option('--depth', action = 'store', - type = 'float', dest = 'depth', default = '3.0', - help = 'Box depth') - - self.OptionParser.add_option('--shelves', action = 'store', - type = 'string', dest = 'shelve_list', default = '', - help = 'semicolon separated list of shelve heigths') - - self.OptionParser.add_option('--groove_depth', action = 'store', - type = 'float', dest = 'groove_depth', default = '0.5', - help = 'Groove depth') - - self.OptionParser.add_option('--tab_size', action = 'store', - type = 'float', dest = 'tab_size', default = '10', - help = 'Approximate tab width (tabs will be evenly spaced along the length of the edge)') - - def effect(self): - """ - Draws a shelved cupboard, based on provided parameters - """ - - # input sanity check and unit conversion - error = False - - if self.options.unit not in self.knownUnits: - doc.errormsg('Error: unknown unit. '+ self.options.unit) - error = True - unit = self.options.unit - - if min(self.options.height, self.options.width, self.options.depth) == 0: - doc.errormsg('Error: Dimensions must be non zero') - error = True - - shelves = [] - - for s in self.options.shelve_list.split(';'): - try: - shelves.append(self.unittouu(str(s).strip() + unit)) - except ValueError: - doc.errormsg('Error: nonnumeric value in shelves (' + s + ')') - error = True - - if error: - exit() - - height = self.unittouu(str(self.options.height) + unit) - width = self.unittouu(str(self.options.width) + unit) - depth = self.unittouu(str(self.options.depth) + unit) - thickness = self.unittouu(str(self.options.thickness) + unit) - groove_depth = self.unittouu(str(self.options.groove_depth) + unit) - tab_size = self.unittouu(str(self.options.tab_size) + unit) - tolerance = self.unittouu(str(self.options.tolerance) + unit) - tool_diameter = self.unittouu(str(self.options.tool_diameter) + unit) - - doc_root = self.document.getroot() - docWidth = self.unittouu(doc_root.get('width')) - docHeigh = self.unittouu(doc_root.attrib['height']) - - layer = doc.layer(doc_root, 'Shelves') - - def H(x): - return doc.Coordinate(x, 0) - - def V(x): - return doc.Coordinate(0, x) - - def tab_count(dist, desired_tab_size): - F = int(dist // desired_tab_size) - if F / 2 % 2 == 0: # make sure we have an odd number of tabs - n = F // 2 - else: - n = (F - 1) // 2 - - return 2 * n + 1 - - # create groups for the different parts - g_l_side = doc.group(layer) - g_r_side = doc.group(layer) - g_top = doc.group(layer) - g_bottom = doc.group(layer) - g_back = doc.group(layer) - g_divider = doc.group(layer) - - h_spacing = H(10 + thickness) - v_spacing = V(10 + thickness) - - v_tab_count = tab_count(height, tab_size) - v_tab = V(height / v_tab_count) - h_tab_count = tab_count(width, tab_size) - h_tab = H(width / h_tab_count) - d_tab_count = tab_count(depth, tab_size) - d_tab_size = depth / d_tab_count - - h_tab_height = V(thickness) - - top_origin = h_spacing * 2 + v_spacing + H(depth) - left_side_origin = h_spacing + v_spacing * 2 + V(depth) - back_origin = left_side_origin + h_spacing + H(depth) - right_side_origin = back_origin + h_spacing + H(width) - bottom_origin = back_origin + v_spacing + V(height) - - def draw_tabbed_edge(parent, edge_start, tab, inset, count, invert = False): - start = edge_start + (inset if invert else doc.Coordinate(0, 0)) - for i in range(count): - if (i % 2 == 0) != invert: - t_offset = inset - else: - t_offset = doc.Coordinate(0, 0) - end = start + tab - #inkex.debug(str((i, start, end, t_offset))) - doc.draw_line(parent, start, end) - if i < count - 1: # skip last one - start = edge_start + t_offset + tab * (i + 1) - doc.draw_line(parent, end, start) - - # top - doc.draw_line(g_top, top_origin, top_origin + H(width)) - draw_tabbed_edge(g_top, top_origin, V(d_tab_size), H(thickness), d_tab_count, False) - draw_tabbed_edge(g_top, top_origin + H(width) , V(d_tab_size), H(-thickness), d_tab_count, False) - draw_tabbed_edge(g_top, top_origin + V(depth), h_tab, V(-thickness), h_tab_count, True) - # groove - groove_style = doc.groove_style - center_v_groove_l = (width - thickness) / 2 - tolerance - groove_l_side = top_origin + H(center_v_groove_l) - groove_r_side = groove_l_side + H(thickness + tolerance * 2) - doc.draw_line(g_top, groove_l_side, groove_l_side + V(depth), groove_style) - doc.draw_line(g_top, groove_r_side, groove_r_side + V(depth), groove_style) - - - # left - doc.draw_line(g_l_side, left_side_origin, left_side_origin + V(height)) - draw_tabbed_edge(g_l_side, left_side_origin + H(depth), v_tab, H(-thickness), v_tab_count, True) - draw_tabbed_edge(g_l_side, left_side_origin, H(d_tab_size), V(thickness), d_tab_count, True) - draw_tabbed_edge(g_l_side, left_side_origin + V(height), H(d_tab_size), V(-thickness), d_tab_count, True) - - # back - draw_tabbed_edge(g_back, back_origin, v_tab, H(thickness), v_tab_count, False) - draw_tabbed_edge(g_back, back_origin + H(width), v_tab, H(-thickness), v_tab_count, False) - draw_tabbed_edge(g_back, back_origin, h_tab, V(thickness), h_tab_count, False) - draw_tabbed_edge(g_back, back_origin + V(height), h_tab, V(-thickness), h_tab_count, False) - # groove - groove_l_side = back_origin + H(center_v_groove_l) - groove_r_side = groove_l_side + H(thickness + tolerance * 2) - doc.draw_line(g_back, groove_l_side, groove_l_side + V(height), groove_style) - doc.draw_line(g_back, groove_r_side, groove_r_side + V(height), groove_style) - - # right - doc.draw_line(g_r_side, right_side_origin + H(depth), right_side_origin + H(depth) + V(height)) - draw_tabbed_edge(g_r_side, right_side_origin, v_tab, H(thickness), v_tab_count, True) - draw_tabbed_edge(g_r_side, right_side_origin, H(d_tab_size), V(thickness), d_tab_count, True) - draw_tabbed_edge(g_r_side, right_side_origin + V(height), H(d_tab_size), V(-thickness), d_tab_count, True) - - # bottom - doc.draw_line(g_bottom, bottom_origin + V(depth), bottom_origin + V(depth) + H(width)) - draw_tabbed_edge(g_bottom, bottom_origin, V(d_tab_size), H(thickness), d_tab_count, False) - draw_tabbed_edge(g_bottom, bottom_origin + H(width) , V(d_tab_size), H(-thickness), d_tab_count, False) - draw_tabbed_edge(g_bottom, bottom_origin, h_tab, V(thickness), h_tab_count, True) - # groove - groove_l_side = bottom_origin + H(center_v_groove_l) - groove_r_side = groove_l_side + H(thickness + tolerance * 2) - doc.draw_line(g_bottom, groove_l_side, groove_l_side + V(depth), groove_style) - doc.draw_line(g_bottom, groove_r_side, groove_r_side + V(depth), groove_style) - - #shelves - prev_top = 0 - gr_short = thickness - groove_depth + tool_diameter / 2 # avoid that the grooves are visible from the outside - for s in shelves: - s_top = prev_top + thickness + s - tolerance - s_bottom = s_top + thickness + tolerance * 2 - - doc.draw_line(g_l_side, left_side_origin + V(s_top), left_side_origin + V(s_top) + H(depth - gr_short), groove_style) - doc.draw_line(g_l_side, left_side_origin + V(s_bottom), left_side_origin + V(s_bottom) + H(depth - gr_short), groove_style) - - doc.draw_line(g_r_side, right_side_origin + V(s_top) + H(gr_short), right_side_origin + V(s_top) + H(depth), groove_style) - doc.draw_line(g_r_side, right_side_origin + V(s_bottom) + H(gr_short), right_side_origin + V(s_bottom) + H(depth), groove_style) - - doc.draw_line(g_back, back_origin + V(s_top) + H(gr_short), back_origin + V(s_top) + H(width - gr_short), groove_style) - doc.draw_line(g_back, back_origin + V(s_bottom) + H(gr_short), back_origin + V(s_bottom) + H(width - gr_short), groove_style) - - prev_top = s_top - -# Create effect instance and apply it. -effect = Shelves() -effect.affect() diff --git a/extensions/fablabchemnitz_shelves_helper.py b/extensions/fablabchemnitz_shelves_helper.py deleted file mode 100644 index d78ad02..0000000 --- a/extensions/fablabchemnitz_shelves_helper.py +++ /dev/null @@ -1,479 +0,0 @@ -#!/usr/bin/env python -from __future__ import division -import inkex -import simplestyle - - -from math import * -from collections import namedtuple - - -#Note: keep in mind that SVG coordinates start in the top-left corner i.e. with an inverted y-axis - -errormsg = inkex.errormsg -debug = inkex.debug - -default_style = simplestyle.formatStyle( - {'stroke': '#000000', - 'stroke-width': '1', - 'fill': 'none' - }) - -groove_style = simplestyle.formatStyle( - {'stroke': '#0000FF', - 'stroke-width': '1', - 'fill': 'none' - }) - -mark_style = simplestyle.formatStyle( - {'stroke': '#00FF00', - 'stroke-width': '1', - 'fill': 'none' - }) - -def draw_rectangle(parent, w, h, x, y, rx=0, ry=0, style=default_style): - attribs = { - 'style': style, - 'height': str(h), - 'width': str(w), - 'x': str(x), - 'y': str(y) - } - if rx != 0 and ry != 0: - attribs['rx'] = str(rx) - attribs['ry'] = str(ry) - inkex.etree.SubElement(parent, inkex.addNS('rect', 'svg'), attribs) - -def draw_ellipse(parent, rx, ry, center, start_end=(0, 2*pi), style=default_style, transform=''): - ell_attribs = {'style': style, - inkex.addNS('cx', 'sodipodi'): str(center.x), - inkex.addNS('cy', 'sodipodi'): str(center.y), - inkex.addNS('rx', 'sodipodi'): str(rx), - inkex.addNS('ry', 'sodipodi'): str(ry), - inkex.addNS('start', 'sodipodi'): str(start_end[0]), - inkex.addNS('end', 'sodipodi'): str(start_end[1]), - inkex.addNS('open', 'sodipodi'): 'true', #all ellipse sectors we will draw are open - inkex.addNS('type', 'sodipodi'): 'arc', - 'transform': transform - } - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), ell_attribs) - - -def draw_arc(parent, rx, ry, x_axis_rot, style=default_style): - arc_attribs = {'style': style, - 'rx': str(rx), - 'ry': str(ry), - 'x-axis-rotation': str(x_axis_rot), - 'large-arc': '', - 'sweep': '', - 'x': '', - 'y': '' - } - #name='part' - style = {'stroke': '#000000', 'fill': 'none'} - drw = {'style':simplestyle.formatStyle(style),inkex.addNS('label','inkscape'):name,'d':XYstring} - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), drw) - inkex.addNS('', 'svg') - -def draw_text(parent, coordinate, txt, style=default_style): - text = inkex.etree.Element(inkex.addNS('text', 'svg')) - text.text = txt - text.set('x', str(coordinate.x)) - text.set('y', str(coordinate.y)) - style = {'text-align': 'center', 'text-anchor': 'middle'} - text.set('style', simplestyle.formatStyle(style)) - parent.append(text) - -#draw an SVG line segment between the given (raw) points -def draw_line(parent, start, end, style = default_style): - line_attribs = {'style': style, - 'd': 'M '+str(start.x)+','+str(start.y)+' L '+str(end.x)+','+str(end.y)} - - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) - -def layer(parent, layer_name): - layer = inkex.etree.SubElement(parent, 'g') - layer.set(inkex.addNS('label', 'inkscape'), layer_name) - layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') - return layer - -def group(parent): - return inkex.etree.SubElement(parent, 'g') - - -class IntersectionError(ValueError): - """Raised when two lines do not intersect.""" - -def on_segment(pt, start, end): - """Check if pt is between start and end. The three points are presumed to be collinear.""" - pt -= start - end -= start - ex, ey = end.x, end.y - px, py = pt.x, pt.y - px *= cmp(ex, 0) - py *= cmp(ey, 0) - return px >= 0 and px <= abs(ex) and py >= 0 and py <= abs(ey) - -def intersection (s1, e1, s2, e2, on_segments = True): - D = (s1.x - e1.x) * (s2.y - e2.y) - (s1.y - e1.y) * (s2.x - e2.x) - if D == 0: - raise IntersectionError("Lines from {s1} to {e1} and {s2} to {e2} are parallel") - N1 = s1.x * e1.y - s1.y * e1.x - N2 = s2.x * e2.y - s2.y * e2.x - I = ((s2 - e2) * N1 - (s1 - e1) * N2) / D - - if on_segments and not (on_segment(I, s1, e1) and on_segment(I, s2, e2)): - raise IntersectionError("Intersection {0} is not on line segments [{1} -> {2}] [{3} -> {4}]".format(I, s1, e1, s2, e2)) - return I - - -def inner_product(a, b): - return a.x * b.x + a.y * b.y - -class Coordinate: - def __init__(self, x, y): - self.x = float(x) - self.y = float(y) - - @property - def t(self): - return atan2(self.y, self.x) - - #@t.setter - #def t(self, value): - - @property - def r(self): - return hypot(self.x, self.y) - - #@r.setter - #def r(self, value): - - def __repr__(self): - return self.__str__() - - def __str__(self): - return "(%f, %f)" % (self.x, self.y) - - def __eq__(self, other): - return self.x == other.x and self.y == other.y - - def __add__(self, other): - return Coordinate(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return Coordinate(self.x - other.x, self.y - other.y) - - def __mul__(self, factor): - return Coordinate(self.x * factor, self.y * factor) - - def __rmul__(self, other): - return self * other - - def __div__(self, quotient): - return Coordinate(self.x / quotient, self.y / quotient) - - def __truediv__(self, quotient): - return self.__div__(quotient) - - - -class Effect(inkex.Effect): - """ - - """ - def __init__(self, options=None): - inkex.Effect.__init__(self) - self.knownUnits = ['in', 'pt', 'px', 'mm', 'cm', 'm', 'km', 'pc', 'yd', 'ft'] - - if options != None: - for opt in options: - if len(opt) == 2: - self.OptionParser.add_option('--' + opt[0], type = opt[1], dest = opt[0]) - else: - self.OptionParser.add_option('--' + opt[0], type = opt[1], dest = opt[0],default = opt[2], help = opt[3]) - - try: - inkex.Effect.unittouu # unitouu has moved since Inkscape 0.91 - except AttributeError: - try: - def unittouu(self, unit): - return inkex.unittouu(unit) - except AttributeError: - pass - - def effect(self): - """ - - """ - pass - - -def _format_1st(command, is_absolute): - return command.upper() if is_absolute else command.lower() - -class Path: - def __init__(self): - self.nodes = [] - - def move_to(self, coord, absolute=False): - self.nodes.append("{0} {1} {2}".format(_format_1st('m', absolute), coord.x, coord.y)) - - def line_to(self, coord, absolute=False): - self.nodes.append("{0} {1} {2}".format(_format_1st('l', absolute), coord.x, coord.y)) - - def h_line_to(self, dist, absolute=False): - self.nodes.append("{0} {1}".format(_format_1st('h', absolute), dist)) - - def v_line_to(self, dist, absolute=False): - self.nodes.append("{0} {1}".format(_format_1st('v', absolute), dist)) - - def arc_to(self, rx, ry, x, y, rotation=0, pos_sweep=True, large_arc=False, absolute=False): - self.nodes.append("{0} {1} {2} {3} {4} {5} {6} {7}".format(_format_1st('a', absolute), rx, ry, rotation, 1 if large_arc else 0, 1 if pos_sweep else 0, x, y)) - - def close(self): - self.nodes.append('z') - - def path(self, parent, style): - attribs = {'style': style, - 'd': ' '.join(self.nodes)} - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), attribs) - - def curve(parent, segments, style, closed=True): - #pathStr = 'M '+ segments[0] - pathStr = ' '.join(segments) - if closed: - pathStr += ' z' - attributes = { - 'style': style, - 'd': pathStr} - inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), attributes) - - def remove_last(self): - self.nodes.pop() - - -PathPoint = namedtuple('PathPoint', 't coord tangent curvature c_dist') - -class PathSegment(): - - def __init__(self): - raise NotImplementedError - - @property - def lenth(self): - raise NotImplementedError - - def subdivide(self, part_length): - raise NotImplementedError - # also need: - - # find a way do do curvature dependent spacing - # - based on deviation from a standard radius? - # - or ratio between thickness and curvature? - #def point_at_distance(d): - # pass - - -class Line(PathSegment): - - def __init__(self, start, end): - self.start = start - self.end = end - - @property - def length(self): - return (self.end - self.start).r - - def subdivide(self, part_length, start_offset=0): # note: start_offset should be smaller than part_length - nr_parts = int((self.length - start_offset) // part_length) - k_o = start_offset / self.length - k2t = lambda k : k_o + k * part_length / self.length - pp = lambda t : PathPoint(t, self.start + t * (self.end - self.start), self.end - self.start, 0, t * self.length) - points = [pp(k2t(k)) for k in range(nr_parts + 1)] - return(points, self.length - points[-1].c_dist) - - - -class BezierCurve(PathSegment): - nr_points = 10 - def __init__(self, P): # number of points is limited to 3 or 4 - - if len(P) == 3: # quadratic - self.B = lambda t : (1 - t)**2 * P[0] + 2 * (1 - t) * t * P[1] + t**2 * P[2] - Bd = lambda t : 2 * (1 - t) * (P[1] - P[0]) + 2 * t * (P[2] - P[1]) - Bdd = lambda t : 2 * (P[2] - 2 * P[1] + P[0]) - elif len(P) == 4: #cubic - self.B = lambda t : (1 - t)**3 * P[0] + 3 * (1 - t)**2 * t * P[1] + 3 * (1 - t) * t**2 * P[2] + t**3 * P[3] - Bd = lambda t : 3 * (1 - t)**2 * (P[1] - P[0]) + 6 * (1 - t) * t * (P[2] - P[1]) + 3 * t**2 * (P[3] - P[2]) - Bdd = lambda t : 6 * (1 - t) * (P[2] - 2 * P[1] + P[0]) + 6 * t * (P[3] - 2 * P[2] + P[1]) - - self.tangent = lambda t : Bd(t) - self.curvature = lambda t : (Bd(t).x * Bdd(t).y - Bd(t).y * Bdd(t).x) / hypot(Bd(t).x, Bd(t).y)**3 - - self.distances = [0] # cumulative distances for each 't' - prev_pt = self.B(0) - for i in range(self.nr_points): - t = (i + 1) / self.nr_points - pt = self.B(t) - self.distances.append(self.distances[-1] + hypot(prev_pt.x - pt.x, prev_pt.y - pt.y)) - prev_pt = pt - self.length = self.distances[-1] - - @classmethod - def quadratic(cls, start, c, end): - bezier = cls() - - @classmethod - def cubic(cls, start, c1, c2, end): - bezier = cls() - - def __make_eq__(self): - pass - - @property - def length(self): - return self.length - - def subdivide(self, part_length, start_offset=0): - nr_parts = int((self.length - start_offset) / part_length + 10E-10) - print "NR PARTS:", nr_parts, self.length, start_offset, part_length, int(self.length / part_length), self.length - 2 * part_length - k_o = start_offset / self.length - k2t = lambda k : k_o + k * part_length / self.length - points = [self.pathpoint_at_t(k2t(k)) for k in range(nr_parts + 1)] - return(points, self.length - points[-1].c_dist) - - - def pathpoint_at_t(self, t): - """pathpoint on the curve from t=0 to point at t.""" - step = 1 / self.nr_points - pt_idx = int(t / step) - #print "index", pt_idx, self.distances[pt_idx] - length = self.distances[pt_idx] - ip_fact = (t - pt_idx * step) / step - - if ip_fact > 0 and t < 1: # not a perfect match, need to interpolate - length += ip_fact * (self.distances[pt_idx + 1] - self.distances[pt_idx]) - - return PathPoint(t, self.B(t), self.tangent(t), self.curvature(t), length) - - - def t_at_length(self, length): - """interpolated t where the curve is at the given length""" - if length == self.length: - return 1 - i_small = 0 - i_big = self.nr_points + 1 - - while i_big - i_small > 1: # binary search - i_half = i_small + (i_big - i_small) // 2 - if self.distances[i_half] <= length: - i_small = i_half - else: - i_big = i_half - - small_dist = self.distances[i_small] - return i_small / self.nr_points + (length - small_dist) * (self.distances[i_big] - small_dist) # interpolated length - -class Ellipse(): - nrPoints = 1000 #used for piecewise linear circumference calculation (ellipse circumference is tricky to calculate) - # approximate circumfere: c = pi * (3 * (a + b) - sqrt(10 * a * b + 3 * (a ** 2 + b ** 2))) - - def __init__(self, w, h): - self.h = h - self.w = w - EllipsePoint = namedtuple('EllipsePoint', 'angle coord cDist') - self.ellData = [EllipsePoint(0, Coordinate(w/2, 0), 0)] # (angle, x, y, cumulative distance from angle = 0) - angle = 0 - self.angleStep = 2 * pi / self.nrPoints - #note: the render angle (ra) corresponds to the angle from the ellipse center (ca) according to: - # ca = atan(w/h * tan(ra)) - for i in range(self.nrPoints): - angle += self.angleStep - prev = self.ellData[-1] - x, y = w / 2 * cos(angle), h / 2 * sin(angle) - self.ellData.append(EllipsePoint(angle, Coordinate(x, y), prev.cDist + hypot(prev.coord.x - x, prev.coord.y - y))) - self.circumference = self.ellData[-1].cDist - #inkex.debug("circ: %d" % self.circumference) - - def rAngle(self, a): - """Convert an angle measured from ellipse center to the angle used to generate ellData (used for lookups)""" - cf = 0 - if a > pi / 2: - cf = pi - if a > 3 * pi / 2: - cf = 2 * pi - return atan(self.w / self.h * tan(a)) + cf - - def coordinateFromAngle(self, angle): - """Coordinate of the point at angle.""" - return Coordinate(self.w / 2 * cos(angle), self.h / 2 * sin(angle)) - - def notchCoordinate(self, angle, notchHeight): - """Coordinate for a notch at the given angle. The notch is perpendicular to the ellipse.""" - angle %= (2 * pi) - #some special cases to avoid divide by zero: - if angle == 0: - return (0, Coordinate(self.w / 2 + notchHeight, 0)) - elif angle == pi: - return (pi, Coordinate(-self.w / 2 - notchHeight, 0)) - elif angle == pi / 2: - return(pi / 2, doc.Coordinate(0, self.h / 2 + notchHeight)) - elif angle == 3 * pi / 2: - return(3 * pi / 2, Coordinate(0, -self.h / 2 - notchHeight)) - - x = self.w / 2 * cos(angle) - derivative = self.h / self.w * -x / sqrt((self.w / 2) ** 2 - x ** 2) - if angle > pi: - derivative = -derivative - - normal = -1 / derivative - nAngle = atan(normal) - if angle > pi / 2 and angle < 3 * pi / 2: - nAngle += pi - - nCoordinate = self.coordinateFromAngle(angle) + Coordinate(cos(nAngle), sin(nAngle)) * notchHeight - return nCoordinate - - - def distFromAngles(self, a1, a2): - """Distance accross the surface from point at angle a2 to point at angle a2. Measured in CCW sense.""" - i1 = int(self.rAngle(a1) / self.angleStep) - p1 = self.rAngle(a1) % self.angleStep - l1 = self.ellData[i1 + 1].cDist - self.ellData[i1].cDist - i2 = int(self.rAngle(a2) / self.angleStep) - p2 = self.rAngle(a2) % self.angleStep - l2 = self.ellData[i2 + 1].cDist - self.ellData[i2].cDist - if a1 <= a2: - len = self.ellData[i2].cDist - self.ellData[i1].cDist + l2 * p2 - l1 * p1 - else: - len = self.circumference + self.ellData[i2].cDist - self.ellData[i1].cDist - return len - - def angleFromDist(self, startAngle, relDist): - """Returns the angle that you get when starting at startAngle and moving a distance (dist) in CCW direction""" - si = int(self.rAngle(startAngle) / self.angleStep) - p = self.rAngle(startAngle) % self.angleStep - - l = self.ellData[si + 1].cDist - self.ellData[si].cDist - - startDist = self.ellData[si].cDist + p * l - - absDist = relDist + startDist - - if absDist > self.ellData[-1].cDist: # wrap around zero angle - absDist -= self.ellData[-1].cDist - - iMin = 0 - iMax = self.nrPoints - count = 0 - while iMax - iMin > 1: # binary search - count += 1 - iHalf = iMin + (iMax - iMin) // 2 - if self.ellData[iHalf].cDist < absDist: - iMin = iHalf - else: - iMax = iHalf - - stepDist = self.ellData[iMax].cDist - self.ellData[iMin].cDist - return self.ellData[iMin].angle + self.angleStep * (absDist - self.ellData[iMin].cDist)/stepDist diff --git a/extensions/fablabchemnitz_sheriff_star.inx b/extensions/fablabchemnitz_sheriff_star.inx deleted file mode 100644 index 7bb6218..0000000 --- a/extensions/fablabchemnitz_sheriff_star.inx +++ /dev/null @@ -1,44 +0,0 @@ - - - -<_name>Sheriff Star -fablabchemnitz.de.sheriff-star -fablabchemnitz_sheriff_star.py -inkex.py - - - - - 6 - 10 - 58 - false - - - <_param name="help_info" type="description"> -This extension creates a sheriff star in the currently selected circle or ellipse. - -The outer vertices (points of the star) are connected through a point on the (usually hidden) inner circle. This inner connection point is located at an angle halfway between the angles of the two outer vertices. The radius of this inner circle is expressed as a percentage of the radius of the selected circle or ellipse. - -Small circles are placed at the tip of each point of the star. The radius of these small circles is expressed as a percentage of the selected circle's radius (for ellipses, the x-radius is used). - -The components that make up the star are left as separate objects so that additional processing can be performed. - - - - - - - path - - - - - - - - - - diff --git a/extensions/fablabchemnitz_sheriff_star.py b/extensions/fablabchemnitz_sheriff_star.py deleted file mode 100644 index 3e16d09..0000000 --- a/extensions/fablabchemnitz_sheriff_star.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python -""" -Sheriff Star -Create n-pointed sheriff star. -""" -import inkex -from math import * - -def addPathCommand(a, cmd): - for x in cmd: - a.append(str(x)) - -class SheriffStarEffect(inkex.Effect): - - def __init__(self): - inkex.Effect.__init__(self) - self.OptionParser.add_option('--tab', - action = 'store', type = 'string', dest = 'tab') - self.OptionParser.add_option('--points', - action='store', type='int', dest='points', default=5, - help='Number of points (or sides)') - self.OptionParser.add_option('--star-tip-ratio', - action='store', type='float', dest='star_tip_ratio', default=10, - help='Star tip circle % (star tip circle radius as a percentage of the outer radius)') - self.OptionParser.add_option('--inner-ratio', - action='store', type='float', dest='inner_ratio', default=58, - help='Inner circle % (inner radius as a percentage of the outer radius)') - self.OptionParser.add_option('--show-inner-circle', - action='store', type='inkbool', dest='show_inner_circle', default=False, - help='Show inner circle') - - def effect(self): - layer = self.current_layer; - - if len(self.selected) == 0: - inkex.errormsg('Please select a circle or ellipse.') - exit() - - numValid = 0 - for id, obj in self.selected.iteritems(): - cx,cy, rx,ry = 0,0, 0,0 - style = '' - isValid = False - if obj.tag == inkex.addNS('circle','svg'): - isValid = True - cx = float(obj.get('cx')) - cy = float(obj.get('cy')) - rx = float(obj.get('r')) - ry = rx - elif obj.tag == inkex.addNS('ellipse', 'svg'): - isValid = True - cx = float(obj.get('cx')) - cy = float(obj.get('cy')) - rx = float(obj.get('rx')) - ry = float(obj.get('ry')) - elif obj.tag == inkex.addNS('path', 'svg'): - if obj.get(inkex.addNS('type', 'sodipodi')) == 'arc': - isValid = True - cx = float(obj.get(inkex.addNS('cx', 'sodipodi'))) - cy = float(obj.get(inkex.addNS('cy', 'sodipodi'))) - rx = float(obj.get(inkex.addNS('rx', 'sodipodi'))) - ry = float(obj.get(inkex.addNS('ry', 'sodipodi'))) - - if not isValid: - continue; - - numValid += 1 - style = obj.get('style') - transform = obj.get('transform') - isEllipse = False - if rx != ry: - isEllipse = True - - skip = 1 - sides = self.options.points - innerRatio = float(self.options.inner_ratio) / 100.0 - starTipRatio = float(self.options.star_tip_ratio) / 100.0 - showInnerCircle = self.options.show_inner_circle - - if showInnerCircle: - if not isEllipse: - cin = inkex.etree.SubElement(layer, inkex.addNS('circle','svg')) - cin.set('r', str(rx * innerRatio)) - else: - cin = inkex.etree.SubElement(layer, inkex.addNS('ellipse','svg')) - cin.set('rx', str(rx * innerRatio)) - cin.set('ry', str(ry * innerRatio)) - cin.set('cx', str(cx)) - cin.set('cy', str(cy)) - cin.set('style', style) - if transform: - cin.set('transform', transform) - - tau = 2*pi - origin = -(tau / 4) - out_pts = [] - in_pts = [] - for i in range(sides): - # Outer points (on outer circle) - theta = (i * (tau / sides)) - px = cx + rx * cos(origin + theta) - py = cy + ry * sin(origin + theta) - out_pts.append([px, py]) - - # Inner points (on inner circle) - theta = ((i + (skip / 2.0)) * (tau / sides)) - px = cx + rx * innerRatio * cos(origin + theta) - py = cy + ry * innerRatio * sin(origin + theta) - in_pts.append([px, py]) - - # Add circles at each star tip. - for pt in out_pts: - cin = inkex.etree.SubElement(layer, inkex.addNS('circle','svg')) - cin.set('r', str(rx * starTipRatio)) - cin.set('cx', str(pt[0])) - cin.set('cy', str(pt[1])) - cin.set('style', style) - if transform: - cin.set('transform', transform) - - pts = [] - pt_done = {} - for i in range(sides): - if i in pt_done: - continue; - - p1 = out_pts[i] - addPathCommand(pts, ['M', p1[0], p1[1]]) - - pt_done[i] = True - start_index = i - curr = start_index - next = (curr + skip) % sides - while next != start_index: - p = out_pts[next] - pt_done[next] = True - - addPathCommand(pts, ['L', in_pts[curr][0], in_pts[curr][1]]) - addPathCommand(pts, ['L', p[0], p[1]]) - - curr = next - next = (curr + skip) % sides - addPathCommand(pts, ['L', in_pts[curr][0], in_pts[curr][1]]) - addPathCommand(pts, ['z']) - - # Create star polygon as a single path. - l1 = inkex.etree.SubElement(layer, inkex.addNS('path','svg')) - l1.set('style', style) - if transform: - l1.set('transform', transform) - l1.set('d', ' '.join(pts)) - - if numValid == 0: - inkex.errormsg('Selection must contain a circle or ellipse.') - -if __name__ == '__main__': - effect = SheriffStarEffect() - effect.affect() diff --git a/extensions/fablabchemnitz_x_agram.inx b/extensions/fablabchemnitz_x_agram.inx deleted file mode 100644 index bf23063..0000000 --- a/extensions/fablabchemnitz_x_agram.inx +++ /dev/null @@ -1,37 +0,0 @@ - - - <_name>X-Agram - fablabchemnitz.de.x-agram - fablabchemnitz_x_agram.py - inkex.py - - - 5 - 2 - 0 - false - true - 50 - - - <_param name="help_info" type="description"> -This extension inscribes a star polygon (pentagram, hexagram, et al.) into the currently selected circle or ellipse. - -If an inner-circle is enabled, then the outer vertices are connected through a point on the inner circle. This inner connection point is located at an angle halfway between the angles of the two outer vertices. - -The components that make up the x-agram are left as separate objects so that additional processing can be performed. - - - - - path - - - - - - - - \ No newline at end of file diff --git a/extensions/fablabchemnitz_x_agram.py b/extensions/fablabchemnitz_x_agram.py deleted file mode 100644 index 9e7d68b..0000000 --- a/extensions/fablabchemnitz_x_agram.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python -""" -X-agram -Create n-pointed star polygons (pentagram, hexagram, etc) -""" -import inkex -from math import * - -def addPathCommand(a, cmd): - for x in cmd: - a.append(str(x)) - -class XGramEffect(inkex.Effect): - - def __init__(self): - inkex.Effect.__init__(self) - self.OptionParser.add_option('--tab', - action = 'store', type = 'string', dest = 'tab') - self.OptionParser.add_option('--points', - action='store', type='int', dest='points', default=5, - help='Number of points (or sides)') - self.OptionParser.add_option('--skip', - action='store', type='int', dest='skip', default=2, - help='Vertex increment when connecting points') - self.OptionParser.add_option('--rotate', - action='store', type='float', dest='rotate', default=0, - help='Rotation angle (clockwise, in degrees)') - self.OptionParser.add_option('--inner-circle', - action='store', type='inkbool', dest='inner_circle', default=False, - help='Connect points via inner circle') - self.OptionParser.add_option('--show-inner-circle', - action='store', type='inkbool', dest='show_inner_circle', default=True, - help='Show inner circle') - self.OptionParser.add_option('--inner-ratio', - action='store', type='int', dest='inner_ratio', default=50, - help='Inner radius percentage (inner radius as a percentage of the outer radius)') - - def effect(self): - layer = self.current_layer; - - if len(self.selected) == 0: - inkex.errormsg('Please select a circle or ellipse.') - exit() - - numValid = 0 - for id, obj in self.selected.iteritems(): - cx,cy, rx,ry = 0,0, 0,0 - style = '' - isValid = False - if obj.tag == inkex.addNS('circle','svg'): - isValid = True - cx = float(obj.get('cx')) - cy = float(obj.get('cy')) - rx = float(obj.get('r')) - ry = rx - elif obj.tag == inkex.addNS('ellipse', 'svg'): - isValid = True - cx = float(obj.get('cx')) - cy = float(obj.get('cy')) - rx = float(obj.get('rx')) - ry = float(obj.get('ry')) - elif obj.tag == inkex.addNS('path', 'svg'): - if obj.get(inkex.addNS('type', 'sodipodi')) == 'arc': - isValid = True - cx = float(obj.get(inkex.addNS('cx', 'sodipodi'))) - cy = float(obj.get(inkex.addNS('cy', 'sodipodi'))) - rx = float(obj.get(inkex.addNS('rx', 'sodipodi'))) - ry = float(obj.get(inkex.addNS('ry', 'sodipodi'))) - - if not isValid: - continue; - - numValid += 1 - style = obj.get('style') - transform = obj.get('transform') - isEllipse = False - if rx != ry: - isEllipse = True - - sides = self.options.points - skip = self.options.skip - rotate = self.options.rotate - useInnerCircle = self.options.inner_circle - showInnerCircle = self.options.show_inner_circle - innerRatio = float(self.options.inner_ratio) / 100.0 - - if useInnerCircle and showInnerCircle: - if not isEllipse: - cin = inkex.etree.SubElement(layer, inkex.addNS('circle','svg')) - cin.set('r', str(rx * innerRatio)) - else: - cin = inkex.etree.SubElement(layer, inkex.addNS('ellipse','svg')) - cin.set('rx', str(rx * innerRatio)) - cin.set('ry', str(ry * innerRatio)) - cin.set('cx', str(cx)) - cin.set('cy', str(cy)) - cin.set('style', style) - if transform: - cin.set('transform', transform) - - tau = 2*pi - origin = -(tau / 4) + (rotate * pi / 180) - out_pts = [] - in_pts = [] - for i in range(sides): - # Outer points (on outer circle) - theta = (i * (tau / sides)) - px = cx + rx * cos(origin + theta) - py = cy + ry * sin(origin + theta) - out_pts.append([px, py]) - - # Inner points (on inner circle) - theta = ((i + (skip / 2.0)) * (tau / sides)) - px = cx + rx * innerRatio * cos(origin + theta) - py = cy + ry * innerRatio * sin(origin + theta) - in_pts.append([px, py]) - - pts = [] - pt_done = {} - for i in range(sides): - if i in pt_done: - continue; - - p1 = out_pts[i] - addPathCommand(pts, ['M', p1[0], p1[1]]) - - pt_done[i] = True - start_index = i - curr = start_index - next = (curr + skip) % sides - while next != start_index: - p = out_pts[next] - pt_done[next] = True - - if useInnerCircle: - addPathCommand(pts, ['L', in_pts[curr][0], in_pts[curr][1]]) - - addPathCommand(pts, ['L', p[0], p[1]]) - - curr = next - next = (curr + skip) % sides - if useInnerCircle: - addPathCommand(pts, ['L', in_pts[curr][0], in_pts[curr][1]]) - addPathCommand(pts, ['z']) - - # Create star polygon as a single path. - l1 = inkex.etree.SubElement(layer, inkex.addNS('path','svg')) - l1.set('style', style) - if transform: - l1.set('transform', transform) - l1.set('d', ' '.join(pts)) - - if numValid == 0: - inkex.errormsg('Selection must contain a circle or ellipse.') - -if __name__ == '__main__': - effect = XGramEffect() - effect.affect()