Date:2015-01-19 02:52:57 (9 years 2 months ago)
Author:Werner Almesberger
Commit:ecb7667c7cd1d8688524276c0aff74a7cb689860
Message:sfc/slicer.py: cleanup and debugging; add various alignment and transformation options

Files: sfc/slicer.py (6 diffs)

Change Details

sfc/slicer.py
2525
2626epsilon = 0.0001 # acceptable math rounding error and slicing offset
2727mech_eps = 0.01 # acceptable mechanical deviation
28margin = None # draw a workpiece at the specified xy distance around
29            # the model (default: none)
28margin = None # draw a rectangular workpiece at the specified xy
29            # distance around the model (default: none)
30z_step = None # maximum Z step (default: unlimited)
31flip = False # flip around X center (default: don't)
32height = None # height of the workpiece above the Z plane (can be
33            # negative). Default: use model dimensions.
34align_top = None # align the Z position of the model to the workpiece
35align_bottom = None
3036
3137
3238def dist(a, b):
...... 
3541    return hypot(pa[0] - pb[0], pa[1] - pb[1])
3642
3743
38def print_vec(v):
44def print_vec(v, z):
3945    p = v.Point
40    print p[0], " ", p[1], " ", p[2] - epsilon
46    print p[0], " ", p[1], " ", z
47
48
49# Make a vector from a point. While we're at it, also apply flipping (if
50# requested).
51
52def vec(p):
53    if flip:
54        return Base.Vector(p[0],
55            bb.YMax - p[1] + bb.YMin, bb.ZMax - p[2] + bb.ZMin)
56    else:
57        return Base.Vector(p[0], p[1], p[2])
58
59#
60# Dump the current Z level (plateau or intermediate level).
61#
62
63
64def dump_level(wires, z):
65    print "# level z = ", z
66
67    if margin is not None:
68        print bb.XMin - margin, " ", bb.YMin - margin, " ", z
69        print bb.XMax + margin, " ", bb.YMin - margin, " ", z
70        print bb.XMax + margin, " ", bb.YMax + margin, " ", z
71        print bb.XMin - margin, " ", bb.YMax + margin, " ", z
72        print bb.XMin - margin, " ", bb.YMin - margin, " ", z
73        print
74
75    for wire in wires:
76        print "# wire = ", wire
77        first = None
78        last = None
79        for e in wire.Edges:
80            v = e.Vertexes[0]
81            if first is None:
82                first = v
83            if last is None or dist(v, last) >= mech_eps:
84                print_vec(v, z)
85            last = v
86        if first is not None:
87            print_vec(first, z)
88            print
89    print
4190
4291
4392def usage():
44    print >>sys.stderr, "usage:", sys.argv[0], "file.stl"
93    print >>sys.stderr, "usage:", sys.argv[0], \
94        "[-a (top|bottom)(+|-)offset] [-f] [-h height]" + \
95        "\t[-b piece_distance] [-s max_step] file.stl"
4596    sys.exit(1)
4697
4798
...... 
54105os.dup2(2, 1)
55106sys.stdout = os.fdopen(stdout, "w")
56107
57opts, args = getopt.getopt(sys.argv[1:], "b:")
108opts, args = getopt.getopt(sys.argv[1:], "a:fh:p:s:")
58109for opt, arg in opts:
59    if opt == "-b":
110    if opt == "-a":
111        if arg[0:3] == "top":
112            align_top = float(arg[3:])
113        elif arg[0:6] == "bottom":
114            align_bottom = float(arg[6:])
115        else:
116            usage()
117    elif opt == "-f":
118        flip = True
119    elif opt == "-h":
120        height = float(arg)
121    elif opt == "-p":
60122        margin = float(arg)
123    elif opt == "-s":
124        z_step = float(arg)
61125    else:
62126        assert False
63127
...... 
65129    usage()
66130
67131#
68# Read the STL mesh
132# Read the STL mesh and determine its bounding box
69133#
70134
71135mesh = Mesh.Mesh(args[0])
136bb = mesh.BoundBox
72137
73138#
74139# The 2.5D model consists of "plateaus" (facets parallel to the xy plane) and
...... 
91156        if nz > epsilon:
92157            inclined += 1
93158            max_nz = max(max_nz, nz)
94        v1 = Base.Vector(facet.Points[0])
95        v2 = Base.Vector(facet.Points[1])
96        v3 = Base.Vector(facet.Points[1])
97        vert.addFacet(v1, v2, v3)
159        vert.addFacet(vec(facet.Points[0]), vec(facet.Points[1]),
160            vec(facet.Points[2]))
98161
99162if inclined:
100163    print >>sys.stderr # FreeCAD progress reporting messes up newlines
...... 
120183#
121184
122185shape = Part.Shape()
123shape.makeShapeFromMesh(mesh.Topology, mech_eps)
124bb = shape.BoundBox
186shape.makeShapeFromMesh(vert.Topology, mech_eps)
187
188z_off = 0
189if height is not None:
190    if align_top is not None:
191        z_off = align_top - bb.ZMax
192        if height > 0:
193            z_off += height
194    if align_bottom is not None:
195        z_off = align_bottom - bb.ZMin
196        if height < 0:
197            z_off += height
125198
126199#
127200# Iterate over all plateaus and determine how they intersect with the walls.
128201# For this, we add a small offset to the z position so that we intersect above
129202# the plateau.
130203#
204# We advance by at most z_step and insert intermediate layers if needed.
205#
131206
132for z in z_levels:
133    print "# level z = ", z
134
135    if margin is not None:
136        print bb.XMin - margin, " ", bb.YMin - margin, " ", z
137        print bb.XMax + margin, " ", bb.YMin - margin, " ", z
138        print bb.XMax + margin, " ", bb.YMax + margin, " ", z
139        print bb.XMin - margin, " ", bb.YMax + margin, " ", z
140        print bb.XMin - margin, " ", bb.YMin - margin, " ", z
141        print
142
143    for wire in shape.slice(Base.Vector(0, 0, 1), z + epsilon):
144        print "# wire = ", wire
145        first = None
146        last = None
147        for e in wire.Edges:
148            v = e.Vertexes[0]
149            if first is None:
150                first = v
151            if last is None or dist(v, last) >= mech_eps:
152                print_vec(v)
153            last = v
154        if first is not None:
155            print_vec(first)
156            print
157    print
158
207if height is not None and height > 0:
208    last_z = height
209else:
210    last_z = None
211if height is not None and height < 0 and z_levels[-1] > height:
212    z_levels.append(height)
213
214for next_z in z_levels:
215    wires = shape.slice(Base.Vector(0, 0, 1), next_z + epsilon)
216    if z_step is None or last_z is None or last_z + z_step >= next_z:
217        dump_level(wires, next_z + z_off)
218    else:
219        d = next_z - last_z
220        n = (d // z_step) + 1
221        for i in range(0, n):
222            dump_level(wires, last_z + (i + 1) * (d / n) + z_off)
223    last_z = next_z
224
159225#
160226# That's all, folks !
161227#

Archive Download the corresponding diff file

Branches:
master



interactive