Commit 05358d3e authored by sumpfralle's avatar sumpfralle

added a base grid for better orientation

moved the dimension visualization to a separated plugin
removed dependency on "Models" plugin from OpenGLWindow


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1190 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 3549f150
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkHBox" id="GridSizeBox">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Major grid:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="MajorGridSizeLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">100mm</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkVSeparator" id="vseparator1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="expand">False</property>
<property name="padding">3</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Minor grid:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="MinorGridSizeLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">20mm</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">4</property>
</packing>
</child>
</object>
</interface>
......@@ -80,6 +80,7 @@ PREFERENCES_DEFAULTS = {
"color_toolpath_cut": (1.0, 0.5, 0.5, 1.0),
"color_toolpath_return": (0.9, 1.0, 0.1, 0.4),
"color_material": (1.0, 0.5, 0.0, 1.0),
"color_grid": (0.75, 1.0, 0.7, 0.55),
"view_light": True,
"view_shadow": True,
"view_polygon": True,
......
......@@ -51,10 +51,10 @@ class OpenGLViewAxes(pycam.Plugins.PluginBase):
GL = self._GL
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
low, high = pycam.Geometry.Model.get_combined_bounds(
self.core.get("models").get_visible())
low, high = [None, None, None], [None, None, None]
self.core.call_chain("get_draw_dimension", low, high)
if None in low or None in high:
low, high = (0, 0, 0), (1, 1, 1)
low, high = (0, 0, 0), (10, 10, 10)
size_x = abs(high[0])
size_y = abs(high[1])
size_z = abs(high[2])
......
......@@ -35,24 +35,43 @@ class OpenGLViewBounds(pycam.Plugins.PluginBase):
40)
self.core.get("register_display_item")("show_bounding_box",
"Show Bounding Box", 40)
self.core.register_chain("get_draw_dimension", self.get_draw_dimension)
self.core.register_event("visualize-items", self.draw_bounds)
self.core.emit_event("visual-item-updated")
return True
def teardown(self):
self.core.unregister_event("visualize-items", self.draw_bounds)
self.core.unregister_chain("get_draw_dimension",
self.get_draw_dimension)
self.core.get("unregister_color")("color_bounding_box")
self.core.get("unregister_display_item")("show_bounding_box")
self.core.emit_event("visual-item-updated")
def draw_bounds(self):
GL = self._GL
def get_draw_dimension(self, low, high):
if not self.core.get("show_bounding_box"):
return
mlow, mhigh = self._get_bounds()
if None in mlow or None in mhigh:
return
for index in range(3):
if (low[index] is None) or (mlow[index] < low[index]):
low[index] = mlow[index]
if (high[index] is None) or (mhigh[index] > high[index]):
high[index] = mhigh[index]
def _get_bounds(self):
bounds = self.core.get("bounds").get_selected()
if not bounds:
return
return ([None, None, None], [None, None, None])
low, high = bounds.get_absolute_limits()
return low, high
def draw_bounds(self):
GL = self._GL
if not self.core.get("show_bounding_box"):
return
low, high = self._get_bounds()
if None in low or None in high:
return
minx, miny, minz = low[0], low[1], low[2]
......
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM 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 3 of the License, or
(at your option) any later version.
PyCAM 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 PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class OpenGLViewDimension(pycam.Plugins.PluginBase):
UI_FILE = "opengl_view_dimension.ui"
DEPENDS = ["Models", "OpenGLWindow"]
CATEGORIES = ["Model", "Visualization", "OpenGL"]
def setup(self):
if self.gui:
import pango
self.core.register_ui("opengl_window", "Dimension",
self.gui.get_object("DimensionTable"), weight=20)
self.core.get("register_display_item")("show_dimensions",
"Show Dimensions", 60),
# Color the dimension value according to the axes.
# For "y" axis: 100% green is too bright on light background - we
# reduce it a bit.
for color, names in (
(pango.AttrForeground(65535, 0, 0, 0, 100),
("model_dim_x_label", "model_dim_x", "ModelCornerXMax",
"ModelCornerXMin", "ModelCornerXSpaces")),
(pango.AttrForeground(0, 50000, 0, 0, 100),
("model_dim_y_label", "model_dim_y", "ModelCornerYMax",
"ModelCornerYMin", "ModelCornerYSpaces")),
(pango.AttrForeground(0, 0, 65535, 0, 100),
("model_dim_z_label", "model_dim_z", "ModelCornerZMax",
"ModelCornerZMin", "ModelCornerZSpaces"))):
attributes = pango.AttrList()
attributes.insert(color)
for name in names:
self.gui.get_object(name).set_attributes(attributes)
self._event_handlers = (
("model-change-after", self.update_model_dimensions),
("visual-item-updated", self.update_model_dimensions),
("model-list-chaned", self.update_model_dimensions))
self.register_event_handlers(self._event_handlers)
return True
def teardown(self):
if self.gui:
self.unregister_event_handlers(self._event_handlers)
self.core.unregister_ui("opengl_window",
self.gui.get_object("DimensionTable"))
self.core.get("unregister_display_item")("show_dimensions")
def update_model_dimensions(self, widget=None):
dimension_bar = self.gui.get_object("DimensionTable")
models = self.core.get("models").get_visible()
low, high = pycam.Geometry.Model.get_combined_bounds(models)
if None in low or None in high:
low, high = (0, 0, 0), (0, 0, 0)
# model corners in 3D view
if None in low or None in high:
# all models are empty
dimension_bar.hide()
return
if self.core.get("show_dimensions"):
dimension_bar.show()
for value, label_suffix in ((low[0], "XMin"), (low[1], "YMin"),
(low[2], "ZMin"), (high[0], "XMax"), (high[1], "YMax"),
(high[2], "ZMax")):
label_name = "ModelCorner%s" % label_suffix
value = "%.3f" % value
self.gui.get_object(label_name).set_label(value)
for name, size in (
("model_dim_x", high[0] - low[0]),
("model_dim_y", high[1] - low[1]),
("model_dim_z", high[2] - low[2])):
self.gui.get_object(name).set_text("%.3f %s" \
% (size, self.core.get("unit_string")))
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM 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 3 of the License, or
(at your option) any later version.
PyCAM 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 PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
import math
class OpenGLViewGrid(pycam.Plugins.PluginBase):
UI_FILE = "opengl_view_grid.ui"
DEPENDS = ["OpenGLWindow"]
CATEGORIES = ["Visualization", "OpenGL"]
MINOR_LINES = 5
MAJOR_LINES = 1
def setup(self):
if self.gui:
self.box = self.gui.get_object("GridSizeBox")
self.core.register_ui("opengl_window", "Grid", self.box, weight=30)
self.core.register_event("visual-item-updated",
self._update_widget_state)
import OpenGL.GL
self._GL = OpenGL.GL
self.core.register_event("visualize-items", self.draw_grid)
self.core.get("register_display_item")("show_grid", "Show Base Grid",
80)
self.core.get("register_color")("color_grid", "Base Grid", 80)
self.core.emit_event("visual-item-updated")
return True
def teardown(self):
if self.gui:
self.core.unregister_event("visual-item-updated",
self._update_widget_state)
self.core.unregister_ui("opengl_window", self.box)
self.core.unregister_event("visualize-items", self.draw_grid)
self.core.get("unregister_color")("color_grid")
self.core.get("unregister_display_item")("show_grid")
self.core.emit_event("visual-item-updated")
def _update_widget_state(self):
if self.core.get("show_grid"):
self.box.show()
else:
self.box.hide()
def draw_grid(self):
if not self.core.get("show_grid"):
return
GL = self._GL
low, high = [None, None, None], [None, None, None]
self.core.call_chain("get_draw_dimension", low, high)
if None in low or None in high:
low, high = (0, 0, 0), (10, 10, 10)
max_value = max(abs(low[0]), abs(low[1]), high[0], high[1])
base_size = 10 ** int(math.log(max_value, 10))
grid_size = math.ceil(float(max_value) / base_size) * base_size
minor_distance = float(base_size) / self.MINOR_LINES
if grid_size / base_size > 5:
minor_distance *= 5
elif grid_size / base_size > 2.5:
minor_distance *= 2.5
major_skip = self.MINOR_LINES / self.MAJOR_LINES
if self.gui:
unit = self.core.get("unit_string")
self.gui.get_object("MajorGridSizeLabel").set_text(
"%g%s" % (minor_distance * major_skip, unit))
self.gui.get_object("MinorGridSizeLabel").set_text(
"%g%s" % (minor_distance, unit))
line_counter = int(math.ceil(grid_size / minor_distance))
GL.glColor4f(*self.core.get("color_grid"))
GL.glFinish()
is_light = GL.glIsEnabled(GL.GL_LIGHTING)
GL.glDisable(GL.GL_LIGHTING)
GL.glBegin(GL.GL_LINES)
grid_low = [-grid_size, -grid_size]
grid_high = [grid_size, grid_size]
for index in range(2):
if high[index] <= 0:
grid_high[index] = 0
if low[index] >= 0:
grid_low[index] = 0
for index in range(-line_counter, line_counter + 1):
position = index * minor_distance
if index % major_skip == 0:
GL.glEnd()
GL.glLineWidth(3)
GL.glBegin(GL.GL_LINES)
if (index == 0) or ((index > 0) and (high[1] > 0)) or \
((index < 0) and (low[1] < 0)):
GL.glVertex3f(grid_low[0], position, 0)
GL.glVertex3f(grid_high[0], position, 0)
if (index == 0) or ((index > 0) and (high[0] > 0)) or \
((index < 0) and (low[0] < 0)):
GL.glVertex3f(position, grid_low[1], 0)
GL.glVertex3f(position, grid_high[1], 0)
if index % major_skip == 0:
GL.glEnd()
GL.glLineWidth(1)
GL.glBegin(GL.GL_LINES)
GL.glEnd()
if is_light:
GL.glEnable(GL.GL_LIGHTING)
......@@ -41,6 +41,7 @@ class OpenGLViewModel(pycam.Plugins.PluginBase):
("model-changed","visual-item-updated"),
("model-list-changed","visual-item-updated"))
self.core.get("register_display_item")("show_model", "Show Model", 10)
self.core.register_chain("get_draw_dimension", self.get_draw_dimension)
self.register_event_handlers(self._event_handlers)
self.core.emit_event("visual-item-updated")
self._cache = {}
......@@ -48,6 +49,8 @@ class OpenGLViewModel(pycam.Plugins.PluginBase):
def teardown(self):
self.unregister_event_handlers(self._event_handlers)
self.core.unregister_chain("get_draw_dimension",
self.get_draw_dimension)
self.core.get("unregister_display_item")("show_model")
self.core.emit_event("visual-item-updated")
......@@ -57,11 +60,26 @@ class OpenGLViewModel(pycam.Plugins.PluginBase):
else:
return None
def _is_visible(self):
return self.core.get("show_model") \
and not (self.core.get("show_simulation") \
and self.core.get("simulation_toolpath_moves"))
def get_draw_dimension(self, low, high):
if self._is_visible():
mlow, mhigh = pycam.Geometry.Model.get_combined_bounds(
self.core.get("models").get_visible())
if None in mlow or None in mhigh:
return
for index in range(3):
if (low[index] is None) or (mlow[index] < low[index]):
low[index] = mlow[index]
if (high[index] is None) or (mhigh[index] > high[index]):
high[index] = mhigh[index]
def draw_model(self):
GL = self._GL
if self.core.get("show_model") \
and not (self.core.get("show_simulation") \
and self.core.get("simulation_toolpath_moves")):
if self._is_visible():
for model in self.core.get("models").get_visible():
color_str = self.core.get("models").get_attr(model, "color")
alpha = self.core.get("models").get_attr(model, "alpha")
......
......@@ -36,22 +36,42 @@ class OpenGLViewToolpath(pycam.Plugins.PluginBase):
60)
self.core.get("register_color")("color_toolpath_return",
"Toolpath rapid", 70)
self.core.register_chain("get_draw_dimension", self.get_draw_dimension)
self.core.get("register_display_item")("show_toolpath", "Show Toolpath", 30),
self.core.emit_event("visual-item-updated")
return True
def teardown(self):
self.core.unregister_chain("get_draw_dimension",
self.get_draw_dimension)
self.core.unregister_event("visualize-items", self.draw_toolpath)
self.core.get("unregister_color")("color_toolpath_cut")
self.core.get("unregister_color")("color_toolpath_return")
self.core.get("unregister_display_item")("show_toolpath")
self.core.emit_event("visual-item-updated")
def draw_toolpath(self):
if self.core.get("show_toolpath") \
def get_draw_dimension(self, low, high):
if self._is_visible():
toolpaths = self.core.get("toolpaths").get_visible()
for tp in toolpaths:
mlow = tp.minx, tp.miny, tp.minz
mhigh = tp.maxx, tp.maxy, tp.maxz
if None in mlow or None in mhigh:
continue
for index in range(3):
if (low[index] is None) or (mlow[index] < low[index]):
low[index] = mlow[index]
if (high[index] is None) or (mhigh[index] > high[index]):
high[index] = mhigh[index]
def _is_visible(self):
return self.core.get("show_toolpath") \
and not self.core.get("toolpath_in_progress") \
and not (self.core.get("show_simulation") \
and self.core.get("simulation_toolpath_moves")):
and self.core.get("simulation_toolpath_moves"))
def draw_toolpath(self):
if self._is_visible():
GL = self._GL
for toolpath in self.core.get("toolpaths").get_visible():
color_rapid = self.core.get("color_toolpath_return")
......
......@@ -26,7 +26,6 @@ try:
import OpenGL.GL as GL
import OpenGL.GLU as GLU
import OpenGL.GLUT as GLUT
import pango
GL_ENABLED = True
except (ImportError, RuntimeError):
GL_ENABLED = False
......@@ -73,8 +72,6 @@ GTK_COLOR_MAX = 65535.0
class OpenGLWindow(pycam.Plugins.PluginBase):
UI_FILE = "opengl.ui"
# TODO: drop the dependecy on "Models" as soon as the calls for get("models") are gone
DEPENDS = ["Models"]
CATEGORIES = ["Visualization", "OpenGL"]
def setup(self):
......@@ -111,6 +108,22 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
skip_obj = self.gui.get_object("DrillProgressFrameSkipControl")
self.core.add_item("drill_progress_max_fps",
skip_obj.get_value, skip_obj.set_value)
# info bar above the model view
detail_box = self.gui.get_object("InfoBox")
def clear_window():
for child in detail_box.get_children():
detail_box.remove(child)
def add_widget_to_window(item, name):
if len(detail_box.get_children()) > 0:
sep = gtk.HSeparator()
detail_box.pack_start(sep)
sep.show()
detail_box.pack_start(item)
item.show()
self.core.register_ui_section("opengl_window",
add_widget_to_window, clear_window)
self.core.register_ui("opengl_window", "Views",
self.gui.get_object("ViewControls"), weight=0)
# color box
color_frame = self.gui.get_object("ColorPrefTab")
color_frame.unparent()
......@@ -141,7 +154,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
# TODO: move support grid and drill to a separate plugin
for name, label, weight in (
("show_support_grid", "Show Support Grid", 20),
("show_dimensions", "Show Dimensions", 60),
("show_drill", "Show Tool", 70),
("show_directions", "Show Directions", 80)):
self.core.get("register_display_item")(name, label, weight)
......@@ -158,7 +170,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
"pressed_button": None}
self.window.connect("delete-event", self.destroy)
self.window.set_default_size(560, 400)
self.container = self.gui.get_object("OpenGLBox")
for obj_name, view in (("ResetView", "reset"),
("LeftView", "left"), ("RightView", "right"),
("FrontView", "front"), ("BackView", "back"),
......@@ -190,26 +201,9 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
(self.area, "motion-notify-event", self.mouse_handler),
(self.area, "button-release-event", self.context_menu_handler),
(self.area, "scroll-event", self.scroll_handler)))
self.container.pack_end(self.area)
self.gui.get_object("OpenGLBox").pack_end(self.area)
self.camera = Camera(self.core, lambda: (self.area.allocation.width,
self.area.allocation.height))
# Color the dimension value according to the axes.
# For "y" axis: 100% green is too bright on light background - we
# reduce it a bit.
for color, names in (
(pango.AttrForeground(65535, 0, 0, 0, 100),
("model_dim_x_label", "model_dim_x", "ModelCornerXMax",
"ModelCornerXMin", "ModelCornerXSpaces")),
(pango.AttrForeground(0, 50000, 0, 0, 100),
("model_dim_y_label", "model_dim_y", "ModelCornerYMax",
"ModelCornerYMin", "ModelCornerYSpaces")),
(pango.AttrForeground(0, 0, 65535, 0, 100),
("model_dim_z_label", "model_dim_z", "ModelCornerZMax",
"ModelCornerZMin", "ModelCornerZSpaces"))):
attributes = pango.AttrList()
attributes.insert(color)
for name in names:
self.gui.get_object(name).set_attributes(attributes)
# add the items buttons (for configuring visible items)
# TODO: enable the context menu
if False and item_buttons:
......@@ -252,8 +246,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
else:
self.context_menu = None
self._event_handlers = (
("model-change-after", self.update_model_dimensions),
("visual-item-updated", self.update_model_dimensions),
("visual-item-updated", self.update_view),
("visualization-state-changed", self._update_widgets),
("model-list-changed", self._restore_latest_view))
......@@ -262,7 +254,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.register_event_handlers(self._event_handlers)
# show the window - the handlers _must_ be registered before "show"
self.area.show()
self.container.show()
toggle_3d.set_active(True)
# refresh display
self.core.emit_event("visual-item-updated")
......@@ -281,8 +272,7 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
for name in ("color_background", "color_model",
"color_support_grid", "color_cutter", "color_material"):
self.core.get("unregister_color")(name)
for name in ("show_support_grid", "show_dimensions", "show_drill",
"show_directions"):
for name in ("show_support_grid", "show_drill", "show_directions"):
self.core.get("unregister_display_item")(name)
self.window.remove_accel_group(self.core.get("gtk-accel-group"))
self.unregister_gtk_handlers(self._gtk_handlers)
......@@ -300,22 +290,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.gui.get_object("Toggle3DView").set_active(self.is_visible)
self.register_gtk_handlers(self._gtk_handlers)
def update_model_dimensions(self, widget=None):
models = self.core.get("models").get_visible()
low, high = pycam.Geometry.Model.get_combined_bounds(models)
if None in low or None in high:
low, high = (0, 0, 0), (0, 0, 0)
# model corners in 3D view
if None in low or None in high:
# all models are empty
return
for value, label_suffix in ((low[0], "XMin"), (low[1], "YMin"),
(low[2], "ZMin"), (high[0], "XMax"), (high[1], "YMax"),
(high[2], "ZMax")):
label_name = "ModelCorner%s" % label_suffix
value = "%.3f" % value
self.gui.get_object(label_name).set_label(value)
def register_display_item(self, name, label, weight=100):
if name in self._display_items:
self.log.debug("Tried to register display item '%s' twice" % name)
......@@ -756,8 +730,8 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
# Determine the biggest dimension (x/y/z) for moving the
# screen's center in relation to this value.
obj_dim = []
low, high = pycam.Geometry.Model.get_combined_bounds(
self.core.get("models").get_visible())
low, high = [None, None, None], [None, None, None]
self.core.call_chain("get_draw_dimension", low, high)
for index in range(3):
obj_dim.append(high[index] - low[index])
max_dim = max(obj_dim)
......@@ -808,21 +782,6 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
# draw the model
draw_complete_model_view(self.core)
self.core.emit_event("visualize-items")
# update the dimension display
s = self.core
dimension_bar = self.gui.get_object("view3ddimension")
low, high = pycam.Geometry.Model.get_combined_bounds(
self.core.get("models").get_visible())
if not (None in low or None in high) and s.get("show_dimensions"):
for name, size in (
("model_dim_x", high[0] - low[0]),
("model_dim_y", high[1] - low[1]),
("model_dim_z", high[2] - low[2])):
self.gui.get_object(name).set_text("%.3f %s" \
% (size, s.get("unit")))
dimension_bar.show()
else:
dimension_bar.hide()
class Camera(object):
......@@ -842,9 +801,9 @@ class Camera(object):
self.auto_adjust_distance()
def _get_low_high_dims(self):
# center the view on the object
models = self.core.get("models").get_visible()
return pycam.Geometry.Model.get_combined_bounds(models)
low, high = [None, None, None], [None, None, None]
self.core.call_chain("get_draw_dimension", low, high)
return low, high
def center_view(self):
center = []
......
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