Commit 282b9065 authored by sumpfralle's avatar sumpfralle

r670@erker: lars | 2010-02-15 14:53:44 +0100

 redraw the bounding box after changing the limit
 do a proper initialization of a model, that was not loaded from a file (e.g. TestModel)
 fix the height calculation of the drill
 fix the order of triangle points when creating the ODE shape


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@128 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 11d4e413
...@@ -41,7 +41,7 @@ if __name__ == "__main__": ...@@ -41,7 +41,7 @@ if __name__ == "__main__":
if not inputfile: if not inputfile:
from pycam.Importers.TestModel import TestModel from pycam.Importers.TestModel import TestModel
gui.model = TestModel() gui.load_model(TestModel())
else: else:
gui.open(inputfile) gui.open(inputfile)
if outputfile and not options.display: if outputfile and not options.display:
......
...@@ -279,6 +279,7 @@ class ProjectGui: ...@@ -279,6 +279,7 @@ class ProjectGui:
for limit in ["minx", "miny", "minz", "maxx", "maxy", "maxz"]: for limit in ["minx", "miny", "minz", "maxx", "maxy", "maxz"]:
obj = self.gui.get_object(limit) obj = self.gui.get_object(limit)
self.settings.add_item(limit, obj.get_value, obj.set_value) self.settings.add_item(limit, obj.get_value, obj.set_value)
obj.connect("value-changed", self.update_view)
# connect the "Bounds" action # connect the "Bounds" action
self.gui.get_object("Minimize bounds").connect("clicked", self.minimize_bounds) self.gui.get_object("Minimize bounds").connect("clicked", self.minimize_bounds)
self.gui.get_object("Reset bounds").connect("clicked", self.reset_bounds) self.gui.get_object("Reset bounds").connect("clicked", self.reset_bounds)
...@@ -304,6 +305,9 @@ class ProjectGui: ...@@ -304,6 +305,9 @@ class ProjectGui:
self.gui.get_object("GenerateToolPathButton").connect("clicked", self.generate_toolpath) self.gui.get_object("GenerateToolPathButton").connect("clicked", self.generate_toolpath)
self.gui.get_object("SaveToolPathButton").connect("clicked", self.save_toolpath) self.gui.get_object("SaveToolPathButton").connect("clicked", self.save_toolpath)
self.gui.get_object("Toggle3dView").connect("toggled", self.toggle_3d_view) self.gui.get_object("Toggle3dView").connect("toggled", self.toggle_3d_view)
# add tool radius for experimental ODE collisions
obj = self.gui.get_object("ToolRadiusControl")
self.settings.add_item("tool_radius", obj.get_value, obj.set_value)
def gui_activity_guard(func): def gui_activity_guard(func):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
...@@ -318,12 +322,12 @@ class ProjectGui: ...@@ -318,12 +322,12 @@ class ProjectGui:
batch_func(*batch_args, **batch_kwargs) batch_func(*batch_args, **batch_kwargs)
return wrapper return wrapper
def update_view(self): def update_view(self, widget=None, data=None):
if self.view3d: if self.view3d:
self.view3d.paint() self.view3d.paint()
def reload_model(self): def reload_model(self, widget=None, data=None):
self.physics = GuiCommon.generate_physics(self.settings) self.physics = GuiCommon.generate_physics(self.settings, self.physics)
if self.view3d: if self.view3d:
self.update_view() self.update_view()
...@@ -441,7 +445,13 @@ class ProjectGui: ...@@ -441,7 +445,13 @@ class ProjectGui:
self.load_model_file(filename=filename) self.load_model_file(filename=filename)
def append_to_queue(self, func, *args, **kwargs): def append_to_queue(self, func, *args, **kwargs):
self._batch_queue.append((func, args, kwargs)) # check if gui is currently active
if self.gui_is_active:
# queue the function call
self._batch_queue.append((func, args, kwargs))
else:
# call the function right now
func(*args, **kwargs)
@gui_activity_guard @gui_activity_guard
def load_model_file(self, widget=None, filename=None): def load_model_file(self, widget=None, filename=None):
...@@ -450,7 +460,10 @@ class ProjectGui: ...@@ -450,7 +460,10 @@ class ProjectGui:
# evaluate "filename" after showing the dialog above - then we will get the new value # evaluate "filename" after showing the dialog above - then we will get the new value
if callable(filename): if callable(filename):
filename = filename() filename = filename()
self.model = pycam.Importers.STLImporter.ImportModel(filename) self.load_model(pycam.Importers.STLImporter.ImportModel(filename))
def load_model(self, model):
self.model = model
# do some initialization # do some initialization
self.append_to_queue(self.reset_bounds) self.append_to_queue(self.reset_bounds)
self.append_to_queue(self.toggle_3d_view, True) self.append_to_queue(self.toggle_3d_view, True)
...@@ -459,6 +472,7 @@ class ProjectGui: ...@@ -459,6 +472,7 @@ class ProjectGui:
@gui_activity_guard @gui_activity_guard
def generate_toolpath(self, widget, data=None): def generate_toolpath(self, widget, data=None):
start_time = time.time() start_time = time.time()
self.reload_model()
radius = float(self.gui.get_object("ToolRadiusControl").get_value()) radius = float(self.gui.get_object("ToolRadiusControl").get_value())
cuttername = None cuttername = None
for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"): for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"):
...@@ -500,7 +514,7 @@ class ProjectGui: ...@@ -500,7 +514,7 @@ class ProjectGui:
self.option = pycam.PathProcessors.PathAccumulator(zigzag=True) self.option = pycam.PathProcessors.PathAccumulator(zigzag=True)
else: else:
self.option = None self.option = None
self.pathgenerator = pycam.PathGenerators.DropCutter(self.cutter, self.model, self.option); self.pathgenerator = pycam.PathGenerators.DropCutter(self.cutter, self.model, self.option, physics=self.physics);
if samples>1: if samples>1:
dx = (maxx-minx)/(samples-1) dx = (maxx-minx)/(samples-1)
else: else:
......
...@@ -18,6 +18,7 @@ from pycam.Importers import * ...@@ -18,6 +18,7 @@ from pycam.Importers import *
from pycam.Exporters import * from pycam.Exporters import *
import pycam.Gui.common as GuiCommon import pycam.Gui.common as GuiCommon
import pycam.Gui.Settings import pycam.Gui.Settings
import time
# leave 10% margin around the model # leave 10% margin around the model
DEFAULT_MARGIN = 0.1 DEFAULT_MARGIN = 0.1
...@@ -69,6 +70,9 @@ class SimpleGui(Tk.Frame): ...@@ -69,6 +70,9 @@ class SimpleGui(Tk.Frame):
GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c)) GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c))
GL.glPopMatrix() GL.glPopMatrix()
def load_model(self, model):
self.model = model
def Redraw(self, event=None): def Redraw(self, event=None):
# default scale and orientation # default scale and orientation
GL.glTranslatef(0,0,-2) GL.glTranslatef(0,0,-2)
...@@ -243,6 +247,7 @@ class SimpleGui(Tk.Frame): ...@@ -243,6 +247,7 @@ class SimpleGui(Tk.Frame):
self.resetView() self.resetView()
def generateToolpath(self): def generateToolpath(self):
start_time = time.time()
radius = float(self.ToolRadius.get()) radius = float(self.ToolRadius.get())
if self.CutterName.get() == "SphericalCutter": if self.CutterName.get() == "SphericalCutter":
self.cutter = SphericalCutter(radius) self.cutter = SphericalCutter(radius)
...@@ -314,6 +319,7 @@ class SimpleGui(Tk.Frame): ...@@ -314,6 +319,7 @@ class SimpleGui(Tk.Frame):
self.toolpath = self.pathgenerator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz, dy, 0, dz) self.toolpath = self.pathgenerator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz, dy, 0, dz)
elif self.Direction.get() == "xy": elif self.Direction.get() == "xy":
self.toolpath = self.pathgenerator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz, dy, dy, dz) self.toolpath = self.pathgenerator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz, dy, dy, dz)
print "Time elapsed: %f" % (time.time() - start_time)
self.ogl.tkRedraw() self.ogl.tkRedraw()
def browseSaveAs(self): def browseSaveAs(self):
......
...@@ -162,11 +162,15 @@ def scale_model(model, scale): ...@@ -162,11 +162,15 @@ def scale_model(model, scale):
matrix = ((scale, 0, 0, 0), (0, scale, 0, 0), (0, 0, scale, 0)) matrix = ((scale, 0, 0, 0), (0, scale, 0, 0), (0, 0, scale, 0))
model.transform(matrix) model.transform(matrix)
def generate_physics(settings): def generate_physics(settings, physics=None):
physics = ode_objects.PhysicalWorld() if physics is None:
physics = ode_objects.PhysicalWorld()
physics.reset() physics.reset()
physics.add_mesh((0, 0, 0), settings.get("model").triangles()) physics.add_mesh((0, 0, 0), settings.get("model").triangles())
height = settings.get("maxz") - settings.get("minz") radius = settings.get("tool_radius")
physics.set_drill(ode_objects.ShapeCylinder(0.1, height), (settings.get("minx"), settings.get("miny"), settings.get("maxz"))) # weird: the normal length of the drill causes the detection to fail at high points of the object
height = 2 * (settings.get("maxz") - settings.get("minz"))
#physics.set_drill(ode_objects.ShapeCylinder(radius, height), (settings.get("minx"), settings.get("miny"), settings.get("maxz")))
physics.set_drill(ode_objects.ShapeCylinder(radius, height), (0, 0, height/2.0))
return physics return physics
...@@ -11,7 +11,7 @@ def convert_triangles_to_vertices_faces(triangles): ...@@ -11,7 +11,7 @@ def convert_triangles_to_vertices_faces(triangles):
id_index_map = {} id_index_map = {}
for t in triangles: for t in triangles:
coords = [] coords = []
for p in (t.p1, t.p2, t.p3): for p in (t.p1, t.p3, t.p2):
# add the point to the id/index mapping, if necessary # add the point to the id/index mapping, if necessary
if not id_index_map.has_key(p.id): if not id_index_map.has_key(p.id):
corners.append((p.x, p.y, p.z)) corners.append((p.x, p.y, p.z))
...@@ -29,6 +29,7 @@ class PhysicalWorld: ...@@ -29,6 +29,7 @@ class PhysicalWorld:
self._geoms = [] self._geoms = []
self._contacts = ode.JointGroup() self._contacts = ode.JointGroup()
self._drill = None self._drill = None
self._drill_offset = None
self._collision_detected = False self._collision_detected = False
def reset(self): def reset(self):
...@@ -37,6 +38,7 @@ class PhysicalWorld: ...@@ -37,6 +38,7 @@ class PhysicalWorld:
self._geoms = [] self._geoms = []
self._contacts = ode.JointGroup() self._contacts = ode.JointGroup()
self._drill = None self._drill = None
self._drill_offset = None
self._collision_detected = False self._collision_detected = False
def _add_geom(self, geom, position, append=True): def _add_geom(self, geom, position, append=True):
...@@ -44,7 +46,8 @@ class PhysicalWorld: ...@@ -44,7 +46,8 @@ class PhysicalWorld:
body.setPosition(position) body.setPosition(position)
body.setGravityMode(False) body.setGravityMode(False)
geom.setBody(body) geom.setBody(body)
self._geoms.append(geom) if append:
self._geoms.append(geom)
def add_mesh(self, position, triangles): def add_mesh(self, position, triangles):
mesh = ode.TriMeshData() mesh = ode.TriMeshData()
...@@ -58,14 +61,19 @@ class PhysicalWorld: ...@@ -58,14 +61,19 @@ class PhysicalWorld:
self._add_geom(geom, position) self._add_geom(geom, position)
def set_drill(self, shape, position): def set_drill(self, shape, position):
geom = ode.GeomTransform(self._space) #geom = ode.GeomTransform(self._space)
geom.setGeom(shape) #geom.setOffset(position)
self._add_geom(geom, position, append=False) #geom.setGeom(shape)
self._drill = geom #shape.setOffset(position)
self._space.add(shape)
self._add_geom(shape, position, append=False)
self._drill_offset = position
self._drill = shape
def set_drill_position(self, position): def set_drill_position(self, position):
if self._drill: if self._drill:
self._drill.getBody().setPosition(position) position = (position[0] + self._drill_offset[0], position[1] + self._drill_offset[1], position[2] + self._drill_offset[2])
self._drill.setPosition(position)
def _collision_callback(self, dummy, geom1, geom2): def _collision_callback(self, dummy, geom1, geom2):
if geom1 is self._drill: if geom1 is self._drill:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment