removed some unwanted extensions
This commit is contained in:
parent
eaa59837dd
commit
6241edb17a
@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<inkscape-extension>
|
|
||||||
<_name>Encoder Disk Generator</_name>
|
|
||||||
<id>fablabchemnitz.de.encoder_disk_generator</id>
|
|
||||||
<param name="tab" type="notebook">
|
|
||||||
<page name="rotary_enc" _gui-text="Rotary encoder">
|
|
||||||
<param name="diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the encoder disk">0.0</param>
|
|
||||||
<param name="hole_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the center hole">0.0</param>
|
|
||||||
<param name="segments" type="int" min="1" max="10000" _gui-text="Number of segments">1</param>
|
|
||||||
<param name="outer_encoder_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the outer encoder disk">0.0</param>
|
|
||||||
<param name="outer_encoder_width" type="float" min="1.0" max="1000.0" _gui-text="Width of the outer encoder disk">0.0</param>
|
|
||||||
<param name="inner_encoder_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the inner encoder disk">0.0</param>
|
|
||||||
<param name="inner_encoder_width" type="float" min="1.0" max="1000.0" _gui-text="Width of the inner encoder disk">0.0</param>
|
|
||||||
</page>
|
|
||||||
<page name="brgc" _gui-text="Binary reflected gray code (BRGC)">
|
|
||||||
<param name="brgc_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the encoder disk">0.0</param>
|
|
||||||
<param name="brgc_hole_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the center hole">0.0</param>
|
|
||||||
<param name="bits" type="int" min="1" max="32" _gui-text="Number of bits/tracks">1</param>
|
|
||||||
<param name="encoder_diameter" type="float" min="1.0" max="1000.0" _gui-text="Outer diameter of the last track">0.0</param>
|
|
||||||
<param name="track_width" type="float" min="1.0" max="1000.0" _gui-text="Width of one track">0.0</param>
|
|
||||||
<param name="track_distance" type="float" min="0.0" max="1000.0" _gui-text="Distance between tracks">0.0</param>
|
|
||||||
</page>
|
|
||||||
<page name="stgc" _gui-text="Single-track gray code (STGC)">
|
|
||||||
<param name="stgc_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the encoder disk">0.0</param>
|
|
||||||
<param name="stgc_hole_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the center hole">0.0</param>
|
|
||||||
<param name="cutouts" type="int" min="1" max="5" _gui-text="Number of cutouts">1</param>
|
|
||||||
<param name="sensors" type="int" min="1" max="36" _gui-text="Number of sensors">1</param>
|
|
||||||
<param name="stgc_encoder_diameter" type="float" min="1.0" max="1000.0" _gui-text="Outer diameter of track">0.0</param>
|
|
||||||
<param name="stgc_track_width" type="float" min="1.0" max="1000.0" _gui-text="Width of one track">0.0</param>
|
|
||||||
</page>
|
|
||||||
<page name="bitmap_enc" _gui-text="Bitmap encoder">
|
|
||||||
<param name="bm_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the encoder disk">30.0</param>
|
|
||||||
<param name="bm_hole_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the center hole">5.0</param>
|
|
||||||
<param name="bm_bits" type="string" _gui-text="Bits for segments">010011110111000010001101</param>
|
|
||||||
<param name="bm_outer_encoder_diameter" type="float" min="0.0" max="1000.0" _gui-text="Diameter of the outer encoder disk">25.0</param>
|
|
||||||
<param name="bm_outer_encoder_width" type="float" min="1.0" max="1000.0" _gui-text="Width of the outer encoder disk">10.0</param>
|
|
||||||
</page>
|
|
||||||
</param>
|
|
||||||
<effect>
|
|
||||||
<object-type>all</object-type>
|
|
||||||
<effects-menu>
|
|
||||||
<submenu _name="FabLab Chemnitz">
|
|
||||||
<submenu _name="Shape/Pattern from Generator" />
|
|
||||||
</submenu>
|
|
||||||
</effects-menu>
|
|
||||||
</effect>
|
|
||||||
<script>
|
|
||||||
<command reldir="extensions" interpreter="python">fablabchemnitz_encoder_disk_generator.py</command>
|
|
||||||
</script>
|
|
||||||
</inkscape-extension>
|
|
@ -1,404 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import inkex
|
|
||||||
import math
|
|
||||||
import string
|
|
||||||
from lxml import etree
|
|
||||||
from inkex.transforms import Transform
|
|
||||||
|
|
||||||
# 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.arg_parser.add_argument("--tab", default="rotary_enc", help="Selected tab")
|
|
||||||
self.arg_parser.add_argument("--diameter", type=float, default=0.0, help="Diameter of the encoder disk")
|
|
||||||
self.arg_parser.add_argument("--hole_diameter", type=float, default=0.0, help="Diameter of the center hole")
|
|
||||||
self.arg_parser.add_argument("--segments", type=int, default=0, help="Number of segments")
|
|
||||||
self.arg_parser.add_argument("--outer_encoder_diameter", type=float, default=0.0, help="Diameter of the outer encoder disk")
|
|
||||||
self.arg_parser.add_argument("--outer_encoder_width", type=float, default=0.0, help="Width of the outer encoder disk")
|
|
||||||
self.arg_parser.add_argument("--inner_encoder_diameter", type=float, default=0.0, help="Diameter of the inner encoder disk")
|
|
||||||
self.arg_parser.add_argument("--inner_encoder_width", type=float, default=0.0, help="Width of the inner encoder disk")
|
|
||||||
self.arg_parser.add_argument("--bits", type=int, default=1, help="Number of bits/tracks")
|
|
||||||
self.arg_parser.add_argument("--encoder_diameter", type=float, default=0.0, help="Outer diameter of the last track")
|
|
||||||
self.arg_parser.add_argument("--track_width", type=float, default=0.0, help="Width of one track")
|
|
||||||
self.arg_parser.add_argument("--track_distance", type=float, default=0.0, help="Distance between tracks")
|
|
||||||
self.arg_parser.add_argument("--bm_diameter", type=float, default=0.0, help="Diameter of the encoder disk")
|
|
||||||
self.arg_parser.add_argument("--bm_hole_diameter", type=float, default=0.0, help="Diameter of the center hole")
|
|
||||||
self.arg_parser.add_argument("--bm_bits", default="", help="Bits of segments")
|
|
||||||
self.arg_parser.add_argument("--bm_outer_encoder_diameter", type=float, default=0.0, help="Diameter of the outer encoder disk")
|
|
||||||
self.arg_parser.add_argument("--bm_outer_encoder_width", type=float, default=0.0, help="Width of the outer encoder disk")
|
|
||||||
self.arg_parser.add_argument("--brgc_diameter", type=float, default=0.0, help="Diameter of the encoder disk")
|
|
||||||
self.arg_parser.add_argument("--stgc_diameter", type=float, default=0.0, help="Diameter of the encoder disk")
|
|
||||||
self.arg_parser.add_argument("--brgc_hole_diameter", type=float, default=0.0, help="Diameter of the center hole")
|
|
||||||
self.arg_parser.add_argument("--cutouts", type=int, default=1, help="Number of cutouts")
|
|
||||||
self.arg_parser.add_argument("--sensors", type=int, default=1, help="Number of sensors")
|
|
||||||
self.arg_parser.add_argument("--stgc_hole_diameter", type=float, default=0.0, help="Diameter of the center hole")
|
|
||||||
self.arg_parser.add_argument("--stgc_encoder_diameter", type=float, default=0.0, help="Outer diameter of the last track")
|
|
||||||
self.arg_parser.add_argument("--stgc_track_width", type=float, 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 = Transform('rotate(' + str(label_angle + 90) + ')').matrix
|
|
||||||
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 = etree.SubElement(group, inkex.addNS('text', 'svg'), text)
|
|
||||||
#tspanElement = etree.Element(
|
|
||||||
# textElement, '{%s}%s' % (svg_uri, 'tspan'), tspan)
|
|
||||||
textElement.text = string.printable[labelNum % len(string.printable)]
|
|
||||||
|
|
||||||
self.svg.get_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': str(inkex.Style(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):
|
|
||||||
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': str(inkex.Style({'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': str(inkex.Style(
|
|
||||||
{'stroke': 'white', 'fill': 'white', 'stroke-width': '0.1'})),
|
|
||||||
'r': '1'
|
|
||||||
}
|
|
||||||
circle_elements.append(attributes)
|
|
||||||
|
|
||||||
# Attributes for the outer rim, then create it
|
|
||||||
attributes = {
|
|
||||||
'style': str(inkex.Style(
|
|
||||||
{'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 = etree.SubElement(self.svg.get_current_layer(), 'g', {
|
|
||||||
inkex.addNS('label', 'inkscape'): 'Encoder disk',
|
|
||||||
'transform': 'translate' + str(self.svg.namedview.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__':
|
|
||||||
EncoderDiskGenerator().run()
|
|
@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
|
||||||
<_name>Fill With Copies</_name>
|
|
||||||
<id>fablabchemnitz.de.fill_row</id>
|
|
||||||
<param name="help_text" type="description">Fills a row with selected paths (works for rectangle objects too). Original author: Pawel Mosakowski. Edited by Mario Voigt (2020).</param>
|
|
||||||
<param name="gap_x" type="int" min="0" max="100000" _gui-text="Gap in X direction">10</param>
|
|
||||||
<param name="gap_y" type="int" min="0" max="100000" _gui-text="Gap in Y direction">10</param>
|
|
||||||
<effect>
|
|
||||||
<object-type>all</object-type>
|
|
||||||
<effects-menu>
|
|
||||||
<submenu _name="FabLab Chemnitz">
|
|
||||||
<submenu _name="Nesting/Cut Optimization"/>
|
|
||||||
</submenu>
|
|
||||||
</effects-menu>
|
|
||||||
</effect>
|
|
||||||
<script>
|
|
||||||
<command reldir="extensions" interpreter="python">fablabchemnitz_fill_row.py</command>
|
|
||||||
</script>
|
|
||||||
</inkscape-extension>
|
|
@ -1,73 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from inkex import Effect as InkscapeEffect
|
|
||||||
from inkex import etree, addNS
|
|
||||||
from copy import deepcopy
|
|
||||||
from inkex.paths import Path
|
|
||||||
from inkex.transforms import Transform
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
class FillRow(InkscapeEffect):
|
|
||||||
def __init__(self):
|
|
||||||
InkscapeEffect.__init__(self)
|
|
||||||
self.arg_parser.add_argument("--gap_x", type=int, default="10")
|
|
||||||
self.arg_parser.add_argument("--gap_y",type=int, default="10")
|
|
||||||
|
|
||||||
def effect(self):
|
|
||||||
if len(self.svg.selected) > 0:
|
|
||||||
self.total_height = 0
|
|
||||||
for id, node in self.svg.selected.items():
|
|
||||||
self.fill_row(node)
|
|
||||||
|
|
||||||
def fill_row(self, node):
|
|
||||||
#max_line_width = self.svg.unittouu('450mm')
|
|
||||||
#x_start = self.svg.unittouu('3mm')
|
|
||||||
#y_start = self.svg.unittouu('1600mm') - self.svg.unittouu('3mm')
|
|
||||||
#gap_x = gap_y = self.svg.unittouu('10mm')
|
|
||||||
|
|
||||||
svg = self.document.getroot()
|
|
||||||
x_start = 0
|
|
||||||
y_start = self.svg.unittouu(svg.attrib['height'])
|
|
||||||
max_line_width = self.svg.unittouu(svg.get('width'))
|
|
||||||
|
|
||||||
total_width = 0
|
|
||||||
total_height = self.total_height
|
|
||||||
|
|
||||||
group = etree.SubElement(self.svg.get_current_layer(), addNS('g','svg'))
|
|
||||||
|
|
||||||
bbox = node.bounding_box()
|
|
||||||
x = bbox.left
|
|
||||||
y = bbox.top
|
|
||||||
node_width = self.options.gap_x + bbox.width
|
|
||||||
|
|
||||||
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 + bbox.height)
|
|
||||||
|
|
||||||
# translation logic
|
|
||||||
if node_copy.tag == addNS('path','svg'):
|
|
||||||
x_delta = x_dest - x
|
|
||||||
y_delta = y_dest - y
|
|
||||||
|
|
||||||
path = Path(node_copy.attrib['d'])
|
|
||||||
path.translate(x_delta, y_delta, True)
|
|
||||||
node_copy.attrib['d'] = str(Path(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]]
|
|
||||||
Transform(translation_matrix) * node_copy.transform
|
|
||||||
else:
|
|
||||||
node_copy.attrib['x'] = str(x_dest)
|
|
||||||
node_copy.attrib['y'] = str(y_dest)
|
|
||||||
|
|
||||||
total_width += node_width
|
|
||||||
|
|
||||||
self.total_height += group.bounding_box().height + self.options.gap_y
|
|
||||||
|
|
||||||
FillRow().run()
|
|
@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
|
||||||
<_name>Parametric Shelves</_name>
|
|
||||||
<id>fablabchemnitz.de.shelves</id>
|
|
||||||
<param name="unit" type="enum" _gui-text="Unit">
|
|
||||||
<_item value="mm">mm</_item>
|
|
||||||
<_item value="cm">cm</_item>
|
|
||||||
<_item value="m">m</_item>
|
|
||||||
<_item value="km">km</_item>
|
|
||||||
<_item value="in">in</_item>
|
|
||||||
<_item value="ft">ft</_item>
|
|
||||||
<_item value="yd">yd</_item>
|
|
||||||
<_item value="pt">pt</_item>
|
|
||||||
<_item value="px">px</_item>
|
|
||||||
<_item value="pc">pc</_item>
|
|
||||||
</param>
|
|
||||||
<param name="thickness" type="float" min="1.0" max="100.0" _gui-text="Material thickness">1.2</param>
|
|
||||||
<param name="tool_diameter" type="float" min="0.0" _gui-text="Tool diameter (mind the units!)">0.3</param>
|
|
||||||
<param name="tolerance" type="float" min="-10000.0" max="10000.0" _gui-text="Tolerance">0.05</param>
|
|
||||||
<param name="height" type="float" min="0.0" max="10000.0" _gui-text="Height">100</param>
|
|
||||||
<param name="width" type="float" min="0.0" max="10000.0" _gui-text="Width">100</param>
|
|
||||||
<param name="depth" type="float" min="0.0" max="10000.0" _gui-text="Depth">40</param>
|
|
||||||
<param name="shelve_list" type="string" min="0.0" max="10000.0" _gui-text="Shelve heigths (semicolon separated list)">10; 20; 35</param>
|
|
||||||
<param name="groove_depth" type="float" min="0.0" max="10000.0" _gui-text="Groove depth">0.6</param>
|
|
||||||
<param name="tab_size" type="float" min="0.0" max="10000.0" _gui-text="Tab size (approximate; will be resized to evenly fit the side)">10</param>
|
|
||||||
<effect>
|
|
||||||
<object-type>all</object-type>
|
|
||||||
<effects-menu>
|
|
||||||
<submenu _name="FabLab Chemnitz">
|
|
||||||
<submenu _name="Finger-jointed/Tabbed Boxes" />
|
|
||||||
</submenu>
|
|
||||||
</effects-menu>
|
|
||||||
</effect>
|
|
||||||
<script>
|
|
||||||
<command reldir="extensions" interpreter="python">fablabchemnitz_shelves.py</command>
|
|
||||||
</script>
|
|
||||||
</inkscape-extension>
|
|
@ -1,193 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from inkscape_helper.Coordinate import Coordinate
|
|
||||||
import inkex
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
default_style = str(inkex.Style({'stroke': '#000000','stroke-width': '1','fill': 'none'}))
|
|
||||||
groove_style = str(inkex.Style({'stroke': '#0000FF','stroke-width': '1','fill': 'none'}))
|
|
||||||
mark_style = str(inkex.Style({'stroke': '#00FF00','stroke-width': '1','fill': 'none'}))
|
|
||||||
|
|
||||||
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)}
|
|
||||||
|
|
||||||
etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs)
|
|
||||||
|
|
||||||
class Shelves(inkex.Effect):
|
|
||||||
def __init__(self):
|
|
||||||
inkex.Effect.__init__(self)
|
|
||||||
|
|
||||||
self.arg_parser.add_argument('--unit', default = 'cm', help = 'Unit, should be one of ')
|
|
||||||
self.arg_parser.add_argument('--tool_diameter', type = float, default = '0.3', help = 'Tool diameter')
|
|
||||||
self.arg_parser.add_argument('--tolerance', type = float, default = '0.05')
|
|
||||||
self.arg_parser.add_argument('--thickness', type = float, dest = 'thickness', default = '1.2', help = 'Material thickness')
|
|
||||||
self.arg_parser.add_argument('--width', type = float, default = '3.0', help = 'Box width')
|
|
||||||
self.arg_parser.add_argument('--height', type = float, default = '10.0', help = 'Box height')
|
|
||||||
self.arg_parser.add_argument('--depth', type = float, default = '3.0', help = 'Box depth')
|
|
||||||
self.arg_parser.add_argument('--shelve_list',default = '', help = 'semicolon separated list of shelve heigths')
|
|
||||||
self.arg_parser.add_argument('--groove_depth', type = float, default = '0.5', help = 'Groove depth')
|
|
||||||
self.arg_parser.add_argument('--tab_size', type = float, default = '10', help = 'Approximate tab width (tabs will be evenly spaced along the length of the edge)')
|
|
||||||
|
|
||||||
def effect(self):
|
|
||||||
# input sanity check and unit conversion
|
|
||||||
error = False
|
|
||||||
self.knownUnits = ['in', 'pt', 'px', 'mm', 'cm', 'm', 'km', 'pc', 'yd', 'ft']
|
|
||||||
if self.options.unit not in self.knownUnits:
|
|
||||||
inkex.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:
|
|
||||||
inkex.errormsg('Error: Dimensions must be non zero')
|
|
||||||
error = True
|
|
||||||
|
|
||||||
shelves = []
|
|
||||||
|
|
||||||
for s in self.options.shelve_list.split(';'):
|
|
||||||
try:
|
|
||||||
shelves.append(self.svg.unittouu(str(s).strip() + unit))
|
|
||||||
except ValueError:
|
|
||||||
inkex.errormsg('Error: nonnumeric value in shelves (' + s + ')')
|
|
||||||
error = True
|
|
||||||
|
|
||||||
if error:
|
|
||||||
exit()
|
|
||||||
|
|
||||||
height = self.svg.unittouu(str(self.options.height) + unit)
|
|
||||||
width = self.svg.unittouu(str(self.options.width) + unit)
|
|
||||||
depth = self.svg.unittouu(str(self.options.depth) + unit)
|
|
||||||
thickness = self.svg.unittouu(str(self.options.thickness) + unit)
|
|
||||||
groove_depth = self.svg.unittouu(str(self.options.groove_depth) + unit)
|
|
||||||
tab_size = self.svg.unittouu(str(self.options.tab_size) + unit)
|
|
||||||
tolerance = self.svg.unittouu(str(self.options.tolerance) + unit)
|
|
||||||
tool_diameter = self.svg.unittouu(str(self.options.tool_diameter) + unit)
|
|
||||||
|
|
||||||
doc_root = self.document.getroot()
|
|
||||||
docWidth = self.svg.unittouu(doc_root.get('width'))
|
|
||||||
docHeigh = self.svg.unittouu(doc_root.attrib['height'])
|
|
||||||
layer = etree.SubElement(doc_root, 'g')
|
|
||||||
layer.set(inkex.addNS('label', 'inkscape'), 'Shelves')
|
|
||||||
layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
|
|
||||||
|
|
||||||
def H(x):
|
|
||||||
return Coordinate(x, 0)
|
|
||||||
|
|
||||||
def V(x):
|
|
||||||
return 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 = etree.SubElement(layer, 'g')
|
|
||||||
g_r_side = etree.SubElement(layer, 'g')
|
|
||||||
g_top = etree.SubElement(layer, 'g')
|
|
||||||
g_bottom = etree.SubElement(layer, 'g')
|
|
||||||
g_back = etree.SubElement(layer, 'g')
|
|
||||||
g_divider = etree.SubElement(layer, 'g')
|
|
||||||
|
|
||||||
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 Coordinate(0, 0))
|
|
||||||
for i in range(count):
|
|
||||||
if (i % 2 == 0) != invert:
|
|
||||||
t_offset = inset
|
|
||||||
else:
|
|
||||||
t_offset = Coordinate(0, 0)
|
|
||||||
end = start + tab
|
|
||||||
#inkex.utils.debug(str((i, start, end, t_offset)))
|
|
||||||
draw_line(parent, start, end)
|
|
||||||
if i < count - 1: # skip last one
|
|
||||||
start = edge_start + t_offset + tab * (i + 1)
|
|
||||||
draw_line(parent, end, start)
|
|
||||||
|
|
||||||
# top
|
|
||||||
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
|
|
||||||
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)
|
|
||||||
draw_line(g_top, groove_l_side, groove_l_side + V(depth), groove_style)
|
|
||||||
draw_line(g_top, groove_r_side, groove_r_side + V(depth), groove_style)
|
|
||||||
|
|
||||||
|
|
||||||
# left
|
|
||||||
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)
|
|
||||||
draw_line(g_back, groove_l_side, groove_l_side + V(height), groove_style)
|
|
||||||
draw_line(g_back, groove_r_side, groove_r_side + V(height), groove_style)
|
|
||||||
|
|
||||||
# right
|
|
||||||
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
|
|
||||||
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)
|
|
||||||
draw_line(g_bottom, groove_l_side, groove_l_side + V(depth), groove_style)
|
|
||||||
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
|
|
||||||
|
|
||||||
draw_line(g_l_side, left_side_origin + V(s_top), left_side_origin + V(s_top) + H(depth - gr_short), groove_style)
|
|
||||||
draw_line(g_l_side, left_side_origin + V(s_bottom), left_side_origin + V(s_bottom) + H(depth - gr_short), groove_style)
|
|
||||||
|
|
||||||
draw_line(g_r_side, right_side_origin + V(s_top) + H(gr_short), right_side_origin + V(s_top) + H(depth), groove_style)
|
|
||||||
draw_line(g_r_side, right_side_origin + V(s_bottom) + H(gr_short), right_side_origin + V(s_bottom) + H(depth), groove_style)
|
|
||||||
|
|
||||||
draw_line(g_back, back_origin + V(s_top) + H(gr_short), back_origin + V(s_top) + H(width - gr_short), groove_style)
|
|
||||||
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.
|
|
||||||
Shelves().run()
|
|
Reference in New Issue
Block a user