Commit 60549c42 authored by sumpfralle's avatar sumpfralle

added an option for using fixed precision numbers instead of floats

 * only useful for debugging (toolpath generation slows down by a factor of 40)


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@567 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 648901e5
...@@ -23,6 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -23,6 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import number
class BaseCutter(object): class BaseCutter(object):
...@@ -35,7 +36,8 @@ class BaseCutter(object): ...@@ -35,7 +36,8 @@ class BaseCutter(object):
self.location = location self.location = location
if height is None: if height is None:
height = 10 height = 10
self.height = height radius = number(radius)
self.height = number(height)
self.id = BaseCutter.id self.id = BaseCutter.id
BaseCutter.id += 1 BaseCutter.id += 1
self.radius = radius self.radius = radius
...@@ -80,7 +82,7 @@ class BaseCutter(object): ...@@ -80,7 +82,7 @@ class BaseCutter(object):
def set_required_distance(self, value): def set_required_distance(self, value):
if value >= 0: if value >= 0:
self.required_distance = value self.required_distance = number(value)
self.distance_radius = self.radius + self.get_required_distance() self.distance_radius = self.radius + self.get_required_distance()
self.distance_radiussq = self.distance_radius * self.distance_radius self.distance_radiussq = self.distance_radius * self.distance_radius
......
...@@ -21,14 +21,13 @@ You should have received a copy of the GNU General Public License ...@@ -21,14 +21,13 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE, sqrt
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.intersection import intersect_circle_plane, \ from pycam.Geometry.intersection import intersect_circle_plane, \
intersect_circle_point, intersect_circle_line, \ intersect_circle_point, intersect_circle_line, \
intersect_cylinder_point, intersect_cylinder_line intersect_cylinder_point, intersect_cylinder_line
from pycam.Cutters.BaseCutter import BaseCutter from pycam.Cutters.BaseCutter import BaseCutter
import math
try: try:
import OpenGL.GL as GL import OpenGL.GL as GL
...@@ -64,7 +63,7 @@ class CylindricalCutter(BaseCutter): ...@@ -64,7 +63,7 @@ class CylindricalCutter(BaseCutter):
additional_distance = self.get_required_distance() additional_distance = self.get_required_distance()
radius = self.distance_radius radius = self.distance_radius
height = self.height + additional_distance height = self.height + additional_distance
center_height = 0.5 * height - additional_distance center_height = height / 2 - additional_distance
geom = ode.GeomTransform(None) geom = ode.GeomTransform(None)
geom_drill = ode.GeomCylinder(None, radius, height) geom_drill = ode.GeomCylinder(None, radius, height)
geom_drill.setPosition((0, 0, center_height)) geom_drill.setPosition((0, 0, center_height))
...@@ -77,7 +76,7 @@ class CylindricalCutter(BaseCutter): ...@@ -77,7 +76,7 @@ class CylindricalCutter(BaseCutter):
def extend_shape(diff_x, diff_y, diff_z): def extend_shape(diff_x, diff_y, diff_z):
reset_shape() reset_shape()
# see http://mathworld.wolfram.com/RotationMatrix.html # see http://mathworld.wolfram.com/RotationMatrix.html
hypotenuse = math.sqrt(diff_x * diff_x + diff_y * diff_y) hypotenuse = sqrt(diff_x * diff_x + diff_y * diff_y)
# Some paths contain two identical points (e.g. a "touch" of # Some paths contain two identical points (e.g. a "touch" of
# the PushCutter) We don't need any extension for these. # the PushCutter) We don't need any extension for these.
if hypotenuse == 0: if hypotenuse == 0:
...@@ -96,20 +95,20 @@ class CylindricalCutter(BaseCutter): ...@@ -96,20 +95,20 @@ class CylindricalCutter(BaseCutter):
geom_connect_transform = ode.GeomTransform(geom.space) geom_connect_transform = ode.GeomTransform(geom.space)
geom_connect_transform.setBody(geom.getBody()) geom_connect_transform.setBody(geom.getBody())
geom_connect = ode_physics.get_parallelepiped_geom( geom_connect = ode_physics.get_parallelepiped_geom(
(Point(-hypotenuse / 2.0, radius, -diff_z / 2.0), (Point(-hypotenuse / 2, radius, -diff_z / 2),
Point(hypotenuse / 2.0, radius, diff_z / 2.0), Point(hypotenuse / 2, radius, diff_z / 2),
Point(hypotenuse / 2.0, -radius, diff_z / 2.0), Point(hypotenuse / 2, -radius, diff_z / 2),
Point(-hypotenuse / 2.0, -radius, -diff_z / 2.0)), Point(-hypotenuse / 2, -radius, -diff_z / 2)),
(Point(-hypotenuse / 2.0, radius, (Point(-hypotenuse / 2, radius,
self.height - diff_z / 2.0), self.height - diff_z / 2),
Point(hypotenuse / 2.0, Point(hypotenuse / 2,
radius, self.height + diff_z / 2.0), radius, self.height + diff_z / 2),
Point(hypotenuse / 2.0, -radius, Point(hypotenuse / 2, -radius,
self.height + diff_z / 2.0), self.height + diff_z / 2),
Point(-hypotenuse / 2.0, -radius, Point(-hypotenuse / 2, -radius,
self.height - diff_z / 2.0))) self.height - diff_z / 2)))
geom_connect.setRotation(rot_matrix_box) geom_connect.setRotation(rot_matrix_box)
geom_connect.setPosition((hypotenuse / 2.0, 0, radius)) geom_connect.setPosition((hypotenuse / 2, 0, radius))
geom_connect_transform.setGeom(geom_connect) geom_connect_transform.setGeom(geom_connect)
# sort the geoms in order of collision probability # sort the geoms in order of collision probability
geom.children.extend([geom_connect_transform, geom.children.extend([geom_connect_transform,
......
...@@ -23,13 +23,12 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -23,13 +23,12 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry import Matrix from pycam.Geometry import Matrix
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import INFINITE, epsilon from pycam.Geometry.utils import INFINITE, epsilon, sqrt
from pycam.Geometry.intersection import intersect_sphere_plane, \ from pycam.Geometry.intersection import intersect_sphere_plane, \
intersect_sphere_point, intersect_sphere_line, \ intersect_sphere_point, intersect_sphere_line, \
intersect_cylinder_point, intersect_cylinder_line intersect_cylinder_point, intersect_cylinder_line
from pycam.Cutters.BaseCutter import BaseCutter from pycam.Cutters.BaseCutter import BaseCutter
import math
try: try:
import OpenGL.GL as GL import OpenGL.GL as GL
...@@ -45,7 +44,7 @@ class SphericalCutter(BaseCutter): ...@@ -45,7 +44,7 @@ class SphericalCutter(BaseCutter):
BaseCutter.__init__(self, radius, **kwargs) BaseCutter.__init__(self, radius, **kwargs)
self.axis = Point(0, 0, 1) self.axis = Point(0, 0, 1)
self.center = Point(self.location.x, self.location.y, self.center = Point(self.location.x, self.location.y,
self.location.z + radius) self.location.z + self.radius)
def __repr__(self): def __repr__(self):
return "SphericalCutter<%s,%s>" % (self.location, self.radius) return "SphericalCutter<%s,%s>" % (self.location, self.radius)
...@@ -56,7 +55,7 @@ class SphericalCutter(BaseCutter): ...@@ -56,7 +55,7 @@ class SphericalCutter(BaseCutter):
import pycam.Physics.ode_physics as ode_physics import pycam.Physics.ode_physics as ode_physics
additional_distance = self.get_required_distance() additional_distance = self.get_required_distance()
radius = self.radius + additional_distance radius = self.radius + additional_distance
center_height = 0.5 * self.height + radius - additional_distance center_height = self.height / 2 + radius - additional_distance
geom = ode.GeomTransform(None) geom = ode.GeomTransform(None)
geom_drill = ode.GeomCapsule(None, radius, self.height) geom_drill = ode.GeomCapsule(None, radius, self.height)
geom_drill.setPosition((0, 0, center_height)) geom_drill.setPosition((0, 0, center_height))
...@@ -69,7 +68,7 @@ class SphericalCutter(BaseCutter): ...@@ -69,7 +68,7 @@ class SphericalCutter(BaseCutter):
def extend_shape(diff_x, diff_y, diff_z): def extend_shape(diff_x, diff_y, diff_z):
reset_shape() reset_shape()
# see http://mathworld.wolfram.com/RotationMatrix.html # see http://mathworld.wolfram.com/RotationMatrix.html
hypotenuse = math.sqrt(diff_x * diff_x + diff_y * diff_y) hypotenuse = sqrt(diff_x * diff_x + diff_y * diff_y)
# Some paths contain two identical points (e.g. a "touch" of the # Some paths contain two identical points (e.g. a "touch" of the
# PushCutter). We don't need any extension for these. # PushCutter). We don't need any extension for these.
if hypotenuse == 0: if hypotenuse == 0:
...@@ -88,20 +87,20 @@ class SphericalCutter(BaseCutter): ...@@ -88,20 +87,20 @@ class SphericalCutter(BaseCutter):
geom_connect_transform = ode.GeomTransform(geom.space) geom_connect_transform = ode.GeomTransform(geom.space)
geom_connect_transform.setBody(geom.getBody()) geom_connect_transform.setBody(geom.getBody())
geom_connect = ode_physics.get_parallelepiped_geom(( geom_connect = ode_physics.get_parallelepiped_geom((
Point(-hypotenuse / 2.0, radius, -diff_z / 2.0), Point(-hypotenuse / 2, radius, -diff_z / 2),
Point(hypotenuse / 2.0, radius, diff_z / 2.0), Point(hypotenuse / 2, radius, diff_z / 2),
Point(hypotenuse / 2.0, -radius, diff_z / 2.0), Point(hypotenuse / 2, -radius, diff_z / 2),
Point(-hypotenuse / 2.0, -radius, -diff_z / 2.0)), Point(-hypotenuse / 2, -radius, -diff_z / 2)),
(Point(-hypotenuse / 2.0, radius, (Point(-hypotenuse / 2, radius,
self.height - diff_z / 2.0), self.height - diff_z / 2),
Point(hypotenuse / 2.0, radius, Point(hypotenuse / 2, radius,
self.height + diff_z / 2.0), self.height + diff_z / 2),
Point(hypotenuse / 2.0, -radius, Point(hypotenuse / 2, -radius,
self.height + diff_z / 2.0), self.height + diff_z / 2),
Point(-hypotenuse / 2.0, -radius, Point(-hypotenuse / 2, -radius,
self.height - diff_z / 2.0))) self.height - diff_z / 2)))
geom_connect.setRotation(rot_matrix_box) geom_connect.setRotation(rot_matrix_box)
geom_connect.setPosition((hypotenuse / 2.0, 0, radius)) geom_connect.setPosition((hypotenuse / 2, 0, radius))
geom_connect_transform.setGeom(geom_connect) geom_connect_transform.setGeom(geom_connect)
# Create a cylinder, that connects the two half spheres at the # Create a cylinder, that connects the two half spheres at the
# lower end of both drills. # lower end of both drills.
...@@ -116,7 +115,7 @@ class SphericalCutter(BaseCutter): ...@@ -116,7 +115,7 @@ class SphericalCutter(BaseCutter):
cyl_original_vector, cyl_destination_vector)) cyl_original_vector, cyl_destination_vector))
# The rotation is around the center - thus we ignore negative # The rotation is around the center - thus we ignore negative
# diff values. # diff values.
geom_cyl.setPosition((abs(diff_x / 2.0), abs(diff_y / 2.0), geom_cyl.setPosition((abs(diff_x / 2), abs(diff_y / 2),
radius - additional_distance)) radius - additional_distance))
geom_cyl_transform.setGeom(geom_cyl) geom_cyl_transform.setGeom(geom_cyl)
# sort the geoms in order of collision probability # sort the geoms in order of collision probability
......
...@@ -22,7 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,7 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE, number
from pycam.Geometry.intersection import intersect_torus_plane, \ from pycam.Geometry.intersection import intersect_torus_plane, \
intersect_torus_point, intersect_circle_plane, intersect_circle_point, \ intersect_torus_point, intersect_circle_plane, intersect_circle_point, \
intersect_cylinder_point, intersect_cylinder_line, intersect_circle_line intersect_cylinder_point, intersect_cylinder_line, intersect_circle_line
...@@ -42,7 +42,8 @@ class ToroidalCutter(BaseCutter): ...@@ -42,7 +42,8 @@ class ToroidalCutter(BaseCutter):
def __init__(self, radius, minorradius, **kwargs): def __init__(self, radius, minorradius, **kwargs):
BaseCutter.__init__(self, radius, **kwargs) BaseCutter.__init__(self, radius, **kwargs)
self.majorradius = radius-minorradius minorradius = number(minorradius)
self.majorradius = self.radius - minorradius
self.minorradius = minorradius self.minorradius = minorradius
self.axis = Point(0, 0, 1) self.axis = Point(0, 0, 1)
self.center = Point(self.location.x, self.location.y, self.center = Point(self.location.x, self.location.y,
......
...@@ -24,7 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -24,7 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry import TransformableContainer from pycam.Geometry import TransformableContainer
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.Plane import Plane from pycam.Geometry.Plane import Plane
from pycam.Geometry.utils import epsilon from pycam.Geometry.utils import epsilon, sqrt
import math import math
...@@ -97,7 +97,7 @@ class Line(TransformableContainer): ...@@ -97,7 +97,7 @@ class Line(TransformableContainer):
return p.sub(self.closest_point(p)).normsq return p.sub(self.closest_point(p)).normsq
def dist_to_point(self, p): def dist_to_point(self, p):
return math.sqrt(self.dist_to_point_sq(p)) return sqrt(self.dist_to_point_sq(p))
def is_point_in_line(self, p): def is_point_in_line(self, p):
return abs(p.sub(self.p1).norm + p.sub(self.p2).norm - self.len) < epsilon return abs(p.sub(self.p1).norm + p.sub(self.p2).norm - self.len) < epsilon
...@@ -116,8 +116,8 @@ class Line(TransformableContainer): ...@@ -116,8 +116,8 @@ class Line(TransformableContainer):
ortho = (0.0, 1.0) ortho = (0.0, 1.0)
else: else:
ortho = (1.0 / line[0], -1.0 / line[1]) ortho = (1.0 / line[0], -1.0 / line[1])
line_size = math.sqrt((line[0] ** 2) + (line[1] ** 2)) line_size = sqrt((line[0] ** 2) + (line[1] ** 2))
ortho_size = math.sqrt((ortho[0] ** 2) + (ortho[1] ** 2)) ortho_size = sqrt((ortho[0] ** 2) + (ortho[1] ** 2))
ortho_dest_size = line_size / 10.0 ortho_dest_size = line_size / 10.0
ortho = (ortho[0] * ortho_dest_size / ortho_size, ortho = (ortho[0] * ortho_dest_size / ortho_size,
ortho[1] * ortho_dest_size / ortho_size) ortho[1] * ortho_dest_size / ortho_size)
......
...@@ -24,6 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -24,6 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import sqrt, number
import math import math
...@@ -80,7 +81,7 @@ def get_length(vector): ...@@ -80,7 +81,7 @@ def get_length(vector):
@return: the length of a vector is the square root of the dot product @return: the length of a vector is the square root of the dot product
of the vector with itself of the vector with itself
""" """
return math.sqrt(get_dot_product(vector, vector)) return sqrt(get_dot_product(vector, vector))
def get_rotation_matrix_from_to(v_orig, v_dest): def get_rotation_matrix_from_to(v_orig, v_dest):
""" calculate the rotation matrix used to transform one vector into another """ calculate the rotation matrix used to transform one vector into another
...@@ -149,8 +150,8 @@ def get_rotation_matrix_axis_angle(rot_axis, rot_angle): ...@@ -149,8 +150,8 @@ def get_rotation_matrix_axis_angle(rot_axis, rot_angle):
@rtype: tuple(float) @rtype: tuple(float)
@return: the roation @return: the roation
""" """
sin = math.sin(rot_angle) sin = number(math.sin(rot_angle))
cos = math.cos(rot_angle) cos = number(math.cos(rot_angle))
return ((cos + rot_axis[0]*rot_axis[0]*(1-cos), return ((cos + rot_axis[0]*rot_axis[0]*(1-cos),
rot_axis[0]*rot_axis[1]*(1-cos) - rot_axis[2]*sin, rot_axis[0]*rot_axis[1]*(1-cos) - rot_axis[2]*sin,
rot_axis[0]*rot_axis[2]*(1-cos) + rot_axis[1]*sin), rot_axis[0]*rot_axis[2]*(1-cos) + rot_axis[1]*sin),
...@@ -172,7 +173,13 @@ def multiply_vector_matrix(v, m): ...@@ -172,7 +173,13 @@ def multiply_vector_matrix(v, m):
@return: a tuple of 3 floats as the matrix product @return: a tuple of 3 floats as the matrix product
""" """
if len(m) == 9: if len(m) == 9:
m = [number(value) for value in m]
m = ((m[0], m[1], m[2]), (m[3], m[4], m[5]), (m[6], m[7], m[8])) m = ((m[0], m[1], m[2]), (m[3], m[4], m[5]), (m[6], m[7], m[8]))
else:
new_m = []
for column in m:
new_m.append([number(value) for value in column])
v = [number(value) for value in v]
return (v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2], return (v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2],
v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2], v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2],
v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2]) v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2])
......
...@@ -21,7 +21,8 @@ You should have received a copy of the GNU General Public License ...@@ -21,7 +21,8 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import math from pycam.Geometry.utils import sqrt, number
from decimal import Decimal
def _is_near(x, y): def _is_near(x, y):
return abs(x - y) < 1e-6 return abs(x - y) < 1e-6
...@@ -33,9 +34,9 @@ class Point: ...@@ -33,9 +34,9 @@ class Point:
def __init__(self, x, y, z): def __init__(self, x, y, z):
self.id = Point.id self.id = Point.id
Point.id += 1 Point.id += 1
self.x = float(x) self.x = number(x)
self.y = float(y) self.y = number(y)
self.z = float(z) self.z = number(z)
self.reset_cache() self.reset_cache()
def __repr__(self): def __repr__(self):
...@@ -74,13 +75,14 @@ class Point: ...@@ -74,13 +75,14 @@ class Point:
def reset_cache(self): def reset_cache(self):
self.normsq = self.dot(self) self.normsq = self.dot(self)
self.norm = math.sqrt(self.normsq) self.norm = sqrt(self.normsq)
def mul(self, c): def mul(self, c):
c = number(c)
return Point(self.x * c, self.y * c, self.z * c) return Point(self.x * c, self.y * c, self.z * c)
def div(self, c): def div(self, c):
c = float(c) c = number(c)
return Point(self.x / c, self.y / c, self.z / c) return Point(self.x / c, self.y / c, self.z / c)
def add(self, p): def add(self, p):
......
...@@ -24,6 +24,7 @@ from pycam.Geometry.Line import Line ...@@ -24,6 +24,7 @@ from pycam.Geometry.Line import Line
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.Plane import Plane from pycam.Geometry.Plane import Plane
from pycam.Geometry import TransformableContainer from pycam.Geometry import TransformableContainer
from pycam.Geometry.utils import number
import pycam.Geometry.Matrix as Matrix import pycam.Geometry.Matrix as Matrix
import math import math
...@@ -123,7 +124,7 @@ class Polygon(TransformableContainer): ...@@ -123,7 +124,7 @@ class Polygon(TransformableContainer):
p1 = self._points[index] p1 = self._points[index]
p2 = self._points[(index + 1) % len(self._points)] p2 = self._points[(index + 1) % len(self._points)]
value += p1.x * p2.y - p2.x * p1.y value += p1.x * p2.y - p2.x * p1.y
return value / 2.0 return value / 2
def get_max_inside_distance(self): def get_max_inside_distance(self):
""" calculate the maximum distance between two points of the polygon """ calculate the maximum distance between two points of the polygon
...@@ -188,8 +189,11 @@ class Polygon(TransformableContainer): ...@@ -188,8 +189,11 @@ class Polygon(TransformableContainer):
or (len(self) != len(self._lines_cache)): or (len(self) != len(self._lines_cache)):
# recalculate the line cache # recalculate the line cache
lines = [] lines = []
for index in range(len(self._points)): for index in range(len(self._points) - 1):
lines.append(Line(self._points[index], self._points[(index + 1) % len(self._points)])) lines.append(Line(self._points[index], self._points[index + 1]))
# connect the last point with the first only if the polygon is closed
if self._is_closed:
lines.append(Line(self._points[-1], self._points[0]))
self._lines_cache = lines self._lines_cache = lines
return self._lines_cache[:] return self._lines_cache[:]
...@@ -345,6 +349,7 @@ class Polygon(TransformableContainer): ...@@ -345,6 +349,7 @@ class Polygon(TransformableContainer):
return [new_group] return [new_group]
else: else:
return None return None
offset = number(offset)
if offset == 0: if offset == 0:
return [self] return [self]
if offset * 2 >= self.get_max_inside_distance(): if offset * 2 >= self.get_max_inside_distance():
......
...@@ -20,11 +20,10 @@ You should have received a copy of the GNU General Public License ...@@ -20,11 +20,10 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from math import sqrt
#import pycam.Geometry #import pycam.Geometry
from pycam.Utils.polynomials import poly4_roots from pycam.Utils.polynomials import poly4_roots
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE, sqrt
from pycam.Geometry.Plane import Plane from pycam.Geometry.Plane import Plane
from pycam.Geometry.Line import Line from pycam.Geometry.Line import Line
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
......
...@@ -20,6 +20,32 @@ You should have received a copy of the GNU General Public License ...@@ -20,6 +20,32 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import decimal
import math
INFINITE = 10000 INFINITE = 10000
epsilon = 0.0001 epsilon = 0.0001
# use the "decimal" module for fixed precision numbers (only for debugging)
_use_precision = False
def sqrt(value):
# support precision libraries like "decimal" (built-in)
if hasattr(value, "sqrt"):
return value.sqrt()
else:
return math.sqrt(value)
def ceil(value):
if hasattr(value, "next_minus"):
return int((value + number(1).next_minus()) // 1)
else:
return int(math.ceil(value))
def number(value):
if _use_precision:
return decimal.Decimal(str(value))
else:
return float(value)
...@@ -22,6 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,6 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
import pycam.Geometry.Matrix as Matrix import pycam.Geometry.Matrix as Matrix
from pycam.Geometry.utils import sqrt, number
import pycam.Utils.log import pycam.Utils.log
import OpenGL.GL as GL import OpenGL.GL as GL
import OpenGL.GLU as GLU import OpenGL.GLU as GLU
...@@ -94,7 +95,7 @@ class Camera: ...@@ -94,7 +95,7 @@ class Camera:
v["distance"][2]).normalized() v["distance"][2]).normalized()
# The multiplier "2.0" is based on: sqrt(2) + margin -- the squre root # The multiplier "2.0" is based on: sqrt(2) + margin -- the squre root
# makes sure, that the the diagonal fits. # makes sure, that the the diagonal fits.
distv = distv.mul((max_dim * 2.0) / math.sin(v["fovy"]/2)) distv = distv.mul((max_dim * 2) / number(math.sin(v["fovy"] / 2)))
self.view["distance"] = (distv.x, distv.y, distv.z) self.view["distance"] = (distv.x, distv.y, distv.z)
# Adjust the "far" distance for the camera to make sure, that huge # Adjust the "far" distance for the camera to make sure, that huge
# models (e.g. x=1000) are still visible. # models (e.g. x=1000) are still visible.
...@@ -102,6 +103,7 @@ class Camera: ...@@ -102,6 +103,7 @@ class Camera:
def scale_distance(self, scale): def scale_distance(self, scale):
if scale != 0: if scale != 0:
scale = number(scale)
dist = self.view["distance"] dist = self.view["distance"]
self.view["distance"] = (scale * dist[0], scale * dist[1], self.view["distance"] = (scale * dist[0], scale * dist[1],
scale * dist[2]) scale * dist[2])
...@@ -128,21 +130,22 @@ class Camera: ...@@ -128,21 +130,22 @@ class Camera:
factors_x, factors_y = self._get_axes_vectors() factors_x, factors_y = self._get_axes_vectors()
width, height = self._get_screen_dimensions() width, height = self._get_screen_dimensions()
# relation of x/y movement to the respective screen dimension # relation of x/y movement to the respective screen dimension
win_x_rel = ((-2.0 * x_move) / width) / math.sin(self.view["fovy"]) win_x_rel = (-2 * x_move) / float(width) / math.sin(self.view["fovy"])
win_y_rel = ((-2.0 * y_move) / height) / math.sin(self.view["fovy"]) win_y_rel = (-2 * y_move) / float(height) / math.sin(self.view["fovy"])
# This code is completely arbitrarily based on trial-and-error for # This code is completely arbitrarily based on trial-and-error for
# finding a nice movement speed for all distances. # finding a nice movement speed for all distances.
# Anyone with a better approach should just fix this. # Anyone with a better approach should just fix this.
distance_vector = self.get("distance") distance_vector = self.get("distance")
distance = math.sqrt(sum([dim ** 2 for dim in distance_vector])) distance = float(sqrt(sum([dim ** 2 for dim in distance_vector])))
win_x_rel *= math.cos(win_x_rel / distance) ** 20 win_x_rel *= math.cos(win_x_rel / distance) ** 20
win_y_rel *= math.cos(win_y_rel / distance) ** 20 win_y_rel *= math.cos(win_y_rel / distance) ** 20
# update the model position that should be centered on the screen # update the model position that should be centered on the screen
old_center = self.view["center"] old_center = self.view["center"]
new_center = [] new_center = []
for i in range(3): for i in range(3):
new_center.append(old_center[i] + max_model_shift \ new_center.append(old_center[i] \
* (win_x_rel * factors_x[i] + win_y_rel * factors_y[i])) + max_model_shift * (number(win_x_rel) * factors_x[i] \
+ number(win_y_rel) * factors_y[i]))
self.view["center"] = tuple(new_center) self.view["center"] = tuple(new_center)
def rotate_camera_by_screen(self, start_x, start_y, end_x, end_y): def rotate_camera_by_screen(self, start_x, start_y, end_x, end_y):
...@@ -212,7 +215,7 @@ class Camera: ...@@ -212,7 +215,7 @@ class Camera:
# The "up" vector defines, in what proportion each axis of the model is # The "up" vector defines, in what proportion each axis of the model is
# in line with the screen's y axis. # in line with the screen's y axis.
v_up = self.view["up"] v_up = self.view["up"]
factors_y = (v_up[0], v_up[1], v_up[2]) factors_y = (number(v_up[0]), number(v_up[1]), number(v_up[2]))
# Calculate the proportion of each model axis according to the x axis of # Calculate the proportion of each model axis according to the x axis of
# the screen. # the screen.
distv = self.view["distance"] distv = self.view["distance"]
...@@ -638,10 +641,10 @@ def draw_axes(settings): ...@@ -638,10 +641,10 @@ def draw_axes(settings):
size_x = abs(settings.get("maxx")) size_x = abs(settings.get("maxx"))
size_y = abs(settings.get("maxy")) size_y = abs(settings.get("maxy"))
size_z = abs(settings.get("maxz")) size_z = abs(settings.get("maxz"))
size = 1.7 * max(size_x, size_y, size_z) size = number(1.7) * max(size_x, size_y, size_z)
# the divider is just based on playing with numbers # the divider is just based on playing with numbers
scale = size/1500.0 scale = size / number(1500.0)
string_distance = 1.1 * size string_distance = number(1.1) * size
GL.glBegin(GL.GL_LINES) GL.glBegin(GL.GL_LINES)
GL.glColor3f(1, 0, 0) GL.glColor3f(1, 0, 0)
GL.glVertex3f(0, 0, 0) GL.glVertex3f(0, 0, 0)
......
...@@ -30,6 +30,7 @@ import pycam.Toolpath.Generator ...@@ -30,6 +30,7 @@ import pycam.Toolpath.Generator
import pycam.Toolpath import pycam.Toolpath
import pycam.Importers import pycam.Importers
import pycam.Utils.log import pycam.Utils.log
from pycam.Geometry.utils import sqrt
from pycam.Gui.OpenGLTools import ModelViewWindowGL from pycam.Gui.OpenGLTools import ModelViewWindowGL
from pycam.Toolpath import Bounds from pycam.Toolpath import Bounds
from pycam import VERSION from pycam import VERSION
...@@ -39,7 +40,6 @@ import pycam.Physics.ode_physics ...@@ -39,7 +40,6 @@ import pycam.Physics.ode_physics
import gtk import gtk
import webbrowser import webbrowser
import ConfigParser import ConfigParser
import math
import time import time
import logging import logging
import datetime import datetime
...@@ -2260,8 +2260,8 @@ class ProjectGui: ...@@ -2260,8 +2260,8 @@ class ProjectGui:
# proportion = dimension_x / dimension_y # proportion = dimension_x / dimension_y
proportion = (bounding_box["maxx"] - bounding_box["minx"]) \ proportion = (bounding_box["maxx"] - bounding_box["minx"]) \
/ (bounding_box["maxy"] - bounding_box["miny"]) / (bounding_box["maxy"] - bounding_box["miny"])
x_steps = int(math.sqrt(grid_size) * proportion) x_steps = int(sqrt(grid_size) * proportion)
y_steps = int(math.sqrt(grid_size) / proportion) y_steps = int(sqrt(grid_size) / proportion)
simulation_backend = ODEBlocks.ODEBlocks(toolpath.get_tool_settings(), simulation_backend = ODEBlocks.ODEBlocks(toolpath.get_tool_settings(),
toolpath.get_bounding_box(), x_steps=x_steps, y_steps=y_steps) toolpath.get_bounding_box(), x_steps=x_steps, y_steps=y_steps)
self.settings.set("simulation_object", simulation_backend) self.settings.set("simulation_object", simulation_backend)
......
...@@ -20,6 +20,8 @@ You should have received a copy of the GNU General Public License ...@@ -20,6 +20,8 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.Geometry.utils import sqrt
import math import math
import sys import sys
...@@ -215,10 +217,10 @@ def mouseMoved(x, y): ...@@ -215,10 +217,10 @@ def mouseMoved(x, y):
x = float(x) x = float(x)
y = float(y) y = float(y)
a1 = math.atan2(mouseState.y-height/2.0, mouseState.x-width/2.0) a1 = math.atan2(mouseState.y-height/2.0, mouseState.x-width/2.0)
r1 = math.sqrt((mouseState.y - height / 2.0) ** 2 \ r1 = sqrt((mouseState.y - height / 2.0) ** 2 \
+ (mouseState.x - width / 2.0) ** 2) + (mouseState.x - width / 2.0) ** 2)
a2 = math.atan2(y-height/2.0, x-width/2.0) a2 = math.atan2(y-height/2.0, x-width/2.0)
r2 = math.sqrt((y - height / 2.0) ** 2 + (x - width / 2.0) ** 2) r2 = sqrt((y - height / 2.0) ** 2 + (x - width / 2.0) ** 2)
if (mouseState.button == GLUT.GLUT_LEFT_BUTTON) \ if (mouseState.button == GLUT.GLUT_LEFT_BUTTON) \
or (mouseState.button == GLUT.GLUT_RIGHT_BUTTON): or (mouseState.button == GLUT.GLUT_RIGHT_BUTTON):
a3 = math.acos(mouseState.x/width-0.5) a3 = math.acos(mouseState.x/width-0.5)
......
...@@ -22,11 +22,10 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,11 +22,10 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.Geometry import Point from pycam.Geometry import Point
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE, ceil
from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode
from pycam.Utils import ProgressCounter from pycam.Utils import ProgressCounter
import pycam.Utils.log import pycam.Utils.log
import math
log = pycam.Utils.log.get_logger() log = pycam.Utils.log.get_logger()
...@@ -78,8 +77,8 @@ class DropCutter: ...@@ -78,8 +77,8 @@ class DropCutter:
direction, draw_callback=None): direction, draw_callback=None):
quit_requested = False quit_requested = False
# determine step size # determine step size
num_of_x_lines = 1 + int(math.ceil(abs(maxx - minx) / d0)) num_of_x_lines = 1 + ceil(abs(maxx - minx) / d0)
num_of_y_lines = 1 + int(math.ceil(abs(maxy - miny) / d1)) num_of_y_lines = 1 + ceil(abs(maxy - miny) / d1)
x_step = abs(maxx - minx) / max(1, (num_of_x_lines - 1)) x_step = abs(maxx - minx) / max(1, (num_of_x_lines - 1))
y_step = abs(maxy - miny) / max(1, (num_of_y_lines - 1)) y_step = abs(maxy - miny) / max(1, (num_of_y_lines - 1))
x_steps = [(minx + i * x_step) for i in range(num_of_x_lines)] x_steps = [(minx + i * x_step) for i in range(num_of_x_lines)]
...@@ -113,8 +112,7 @@ class DropCutter: ...@@ -113,8 +112,7 @@ class DropCutter:
last_position = None last_position = None
if draw_callback and draw_callback(text="DropCutter: processing " \ if draw_callback and draw_callback(text="DropCutter: processing " \
+ "line %d/%d" % (current_line, num_of_lines), + "line %d/%d" % (current_line, num_of_lines)):
percent=(100.0 * current_line / num_of_lines)):
# cancel requested # cancel requested
quit_requested = True quit_requested = True
break break
......
...@@ -23,12 +23,11 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -23,12 +23,11 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
import pycam.PathProcessors.PathAccumulator import pycam.PathProcessors.PathAccumulator
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE, ceil
from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode, \ from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode, \
get_free_paths_ode, get_free_paths_triangles get_free_paths_ode, get_free_paths_triangles
from pycam.Utils import ProgressCounter from pycam.Utils import ProgressCounter
import pycam.Utils.log import pycam.Utils.log
import math
log = pycam.Utils.log.get_logger() log = pycam.Utils.log.get_logger()
...@@ -51,7 +50,7 @@ class EngraveCutter: ...@@ -51,7 +50,7 @@ class EngraveCutter:
def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None): def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None):
quit_requested = False quit_requested = False
# calculate the number of steps # calculate the number of steps
num_of_layers = 1 + int(math.ceil(abs(maxz - minz) / dz)) num_of_layers = 1 + ceil(abs(maxz - minz) / dz)
if num_of_layers > 1: if num_of_layers > 1:
z_step = abs(maxz - minz) / (num_of_layers - 1) z_step = abs(maxz - minz) / (num_of_layers - 1)
z_steps = [(maxz - i * z_step) for i in range(num_of_layers)] z_steps = [(maxz - i * z_step) for i in range(num_of_layers)]
...@@ -78,7 +77,7 @@ class EngraveCutter: ...@@ -78,7 +77,7 @@ class EngraveCutter:
break break
for line_group in line_groups: for line_group in line_groups:
for line in line_group.next(): for line in line_group.get_lines():
self.GenerateToolPathLinePush(self.pa_push, line, z, self.GenerateToolPathLinePush(self.pa_push, line, z,
draw_callback) draw_callback)
if progress_counter.increment(): if progress_counter.increment():
...@@ -150,7 +149,7 @@ class EngraveCutter: ...@@ -150,7 +149,7 @@ class EngraveCutter:
p2 = Point(line.p2.x, line.p2.y, minz) p2 = Point(line.p2.x, line.p2.y, minz)
distance = line.len distance = line.len
# we want to have at least five steps each # we want to have at least five steps each
num_of_steps = max(5, 1 + int(math.ceil(distance / horiz_step))) num_of_steps = max(5, 1 + ceil(distance / horiz_step))
# steps may be negative # steps may be negative
x_step = (p2.x - p1.x) / (num_of_steps - 1) x_step = (p2.x - p1.x) / (num_of_steps - 1)
y_step = (p2.y - p1.y) / (num_of_steps - 1) y_step = (p2.y - p1.y) / (num_of_steps - 1)
......
...@@ -23,7 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -23,7 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.PathGenerators import get_free_paths_ode, get_free_paths_triangles from pycam.PathGenerators import get_free_paths_ode, get_free_paths_triangles
from pycam.Geometry.utils import epsilon from pycam.Geometry.utils import epsilon, ceil
from pycam.Utils import ProgressCounter from pycam.Utils import ProgressCounter
import math import math
...@@ -45,16 +45,16 @@ class PushCutter: ...@@ -45,16 +45,16 @@ class PushCutter:
diff_z = 0 diff_z = 0
else: else:
diff_z = abs(maxz - minz) diff_z = abs(maxz - minz)
num_of_layers = 1 + int(math.ceil(diff_z / dz)) num_of_layers = 1 + ceil(diff_z / dz)
z_step = diff_z / max(1, (num_of_layers - 1)) z_step = diff_z / max(1, (num_of_layers - 1))
lines_per_layer = 0 lines_per_layer = 0
if dx != 0: if dx != 0:
x_lines_per_layer = 1 + int(math.ceil(abs(maxx - minx) / dx)) x_lines_per_layer = 1 + ceil(abs(maxx - minx) / dx)
x_step = abs(maxx - minx) / max(1, (x_lines_per_layer - 1)) x_step = abs(maxx - minx) / max(1, (x_lines_per_layer - 1))
lines_per_layer += x_lines_per_layer lines_per_layer += x_lines_per_layer
if dy != 0: if dy != 0:
y_lines_per_layer = 1 + int(math.ceil(abs(maxy - miny) / dy)) y_lines_per_layer = 1 + ceil(abs(maxy - miny) / dy)
y_step = abs(maxy - miny) / max(1, (y_lines_per_layer - 1)) y_step = abs(maxy - miny) / max(1, (y_lines_per_layer - 1))
lines_per_layer += y_lines_per_layer lines_per_layer += y_lines_per_layer
...@@ -98,17 +98,17 @@ class PushCutter: ...@@ -98,17 +98,17 @@ class PushCutter:
# calculate the required number of steps in each direction # calculate the required number of steps in each direction
if dx > 0: if dx > 0:
depth_x = math.log(accuracy * abs(maxx - minx) / dx) / math.log(2) depth_x = math.log(accuracy * abs(maxx - minx) / dx) / math.log(2)
depth_x = max(int(math.ceil(depth_x)), 4) depth_x = max(ceil(depth_x), 4)
depth_x = min(depth_x, max_depth) depth_x = min(depth_x, max_depth)
num_of_x_lines = 1 + int(math.ceil(abs(maxx - minx) / dx)) num_of_x_lines = 1 + ceil(abs(maxx - minx) / dx)
x_step = abs(maxx - minx) / max(1, (num_of_x_lines - 1)) x_step = abs(maxx - minx) / max(1, (num_of_x_lines - 1))
x_steps = [minx + i * x_step for i in range(num_of_x_lines)] x_steps = [minx + i * x_step for i in range(num_of_x_lines)]
y_steps = [None] * num_of_x_lines y_steps = [None] * num_of_x_lines
else: else:
depth_y = math.log(accuracy * abs(maxy - miny) / dy) / math.log(2) depth_y = math.log(accuracy * abs(maxy - miny) / dy) / math.log(2)
depth_y = max(int(math.ceil(depth_y)), 4) depth_y = max(ceil(depth_y), 4)
depth_y = min(depth_y, max_depth) depth_y = min(depth_y, max_depth)
num_of_y_lines = 1 + int(math.ceil(abs(maxy - miny) / dy)) num_of_y_lines = 1 + ceil(abs(maxy - miny) / dy)
y_step = abs(maxy - miny) / max(1, (num_of_y_lines - 1)) y_step = abs(maxy - miny) / max(1, (num_of_y_lines - 1))
y_steps = [miny + i * y_step for i in range(num_of_y_lines)] y_steps = [miny + i * y_step for i in range(num_of_y_lines)]
x_steps = [None] * num_of_y_lines x_steps = [None] * num_of_y_lines
......
...@@ -22,9 +22,8 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,9 +22,8 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
__all__ = ["DropCutter", "PushCutter", "EngraveCutter"] __all__ = ["DropCutter", "PushCutter", "EngraveCutter"]
from pycam.Geometry.utils import INFINITE, epsilon from pycam.Geometry.utils import INFINITE, epsilon, sqrt
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
import math
class Hit: class Hit:
...@@ -43,7 +42,7 @@ def get_free_paths_triangles(model, cutter, p1, p2): ...@@ -43,7 +42,7 @@ def get_free_paths_triangles(model, cutter, p1, p2):
x_dist = p2.x - p1.x x_dist = p2.x - p1.x
y_dist = p2.y - p1.y y_dist = p2.y - p1.y
z_dist = p2.z - p1.z z_dist = p2.z - p1.z
xyz_dist = math.sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist) xyz_dist = sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist)
x_frac = x_dist / xyz_dist x_frac = x_dist / xyz_dist
y_frac = y_dist / xyz_dist y_frac = y_dist / xyz_dist
z_frac = z_dist / xyz_dist z_frac = z_dist / xyz_dist
...@@ -134,9 +133,9 @@ def get_free_paths_ode(physics, p1, p2, depth=8): ...@@ -134,9 +133,9 @@ def get_free_paths_ode(physics, p1, p2, depth=8):
if physics.check_collision(): if physics.check_collision():
# collision detected # collision detected
if depth > 0: if depth > 0:
middle_x = (p1.x + p2.x) / 2.0 middle_x = (p1.x + p2.x) / 2
middle_y = (p1.y + p2.y) / 2.0 middle_y = (p1.y + p2.y) / 2
middle_z = (p1.z + p2.z) / 2.0 middle_z = (p1.z + p2.z) / 2
p_middle = Point(middle_x, middle_y, middle_z) p_middle = Point(middle_x, middle_y, middle_z)
group1 = get_free_paths_ode(physics, p1, p_middle, depth - 1) group1 = get_free_paths_ode(physics, p1, p_middle, depth - 1)
group2 = get_free_paths_ode(physics, p_middle, p2, depth - 1) group2 = get_free_paths_ode(physics, p_middle, p2, depth - 1)
...@@ -186,7 +185,7 @@ def get_max_height_ode(physics, x, y, minz, maxz, order=None): ...@@ -186,7 +185,7 @@ def get_max_height_ode(physics, x, y, minz, maxz, order=None):
trips = 0 trips = 0
safe_z = minz safe_z = minz
while trips > 0: while trips > 0:
current_z = (low + high) / 2.0 current_z = (low + high) / 2
physics.set_drill_position((x, y, current_z)) physics.set_drill_position((x, y, current_z))
if physics.check_collision(): if physics.check_collision():
low = current_z low = current_z
......
...@@ -21,6 +21,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -21,6 +21,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.Geometry.Triangle import Triangle from pycam.Geometry.Triangle import Triangle
from pycam.Geometry.utils import number
try: try:
import ode import ode
...@@ -146,7 +147,7 @@ class PhysicalWorld: ...@@ -146,7 +147,7 @@ class PhysicalWorld:
# the cutters' "extend" functions # the cutters' "extend" functions
shape.space = self._space shape.space = self._space
self._add_geom(shape, position, append=False) self._add_geom(shape, position, append=False)
self._drill_offset = position self._drill_offset = [number(value) for value in position]
self._drill = shape self._drill = shape
self.reset_drill() self.reset_drill()
......
...@@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License ...@@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import math from pycam.Geometry.utils import sqrt
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
import ctypes import ctypes
...@@ -93,10 +93,10 @@ class ZBuffer: ...@@ -93,10 +93,10 @@ class ZBuffer:
def add_wave(self, freq=8, damp=3.0): def add_wave(self, freq=8, damp=3.0):
self.changed = True self.changed = True
rmax = math.sqrt(self.y[0]*self.y[0]+self.x[0]*self.x[0]) rmax = sqrt(self.y[0]*self.y[0]+self.x[0]*self.x[0])
for y in range(0, self.yres): for y in range(0, self.yres):
for x in range(0, self.xres): for x in range(0, self.xres):
r = math.sqrt(self.y[y]*self.y[y]+self.x[x]*self.x[x]) r = sqrt(self.y[y]*self.y[y]+self.x[x]*self.x[x])
self.buf[y][x].z = 1 + math.cos(r / rmax * r / rmax * math.pi \ self.buf[y][x].z = 1 + math.cos(r / rmax * r / rmax * math.pi \
* freq) / (1 + damp * (r / rmax)) * freq) / (1 + damp * (r / rmax))
self.buf[y][x].changed = True self.buf[y][x].changed = True
......
...@@ -21,6 +21,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -21,6 +21,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter
from pycam.Geometry.utils import number
import pycam.PathProcessors import pycam.PathProcessors
import pycam.Cutters import pycam.Cutters
import pycam.Toolpath.SupportGrid import pycam.Toolpath.SupportGrid
...@@ -57,8 +58,8 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None): ...@@ -57,8 +58,8 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
def generate_toolpath(model, tool_settings=None, def generate_toolpath(model, tool_settings=None,
bounds_low=None, bounds_high=None, direction="x", bounds_low=None, bounds_high=None, direction="x",
path_generator="DropCutter", path_postprocessor="ZigZagCutter", path_generator="DropCutter", path_postprocessor="ZigZagCutter",
material_allowance=0.0, safety_height=None, overlap=0.0, step_down=0.0, material_allowance=0, safety_height=None, overlap=0, step_down=0,
engrave_offset=0.0, support_grid_distance_x=None, engrave_offset=0, support_grid_distance_x=None,
support_grid_distance_y=None, support_grid_thickness=None, support_grid_distance_y=None, support_grid_thickness=None,
support_grid_height=None, support_grid_offset_x=None, support_grid_height=None, support_grid_offset_x=None,
support_grid_offset_y=None, support_grid_adjustments_x=None, support_grid_offset_y=None, support_grid_adjustments_x=None,
...@@ -116,16 +117,20 @@ def generate_toolpath(model, tool_settings=None, ...@@ -116,16 +117,20 @@ def generate_toolpath(model, tool_settings=None,
@return: the resulting toolpath object or an error string in case of invalid @return: the resulting toolpath object or an error string in case of invalid
arguments arguments
""" """
overlap = number(overlap)
step_down = number(step_down)
safety_height = number(safety_height)
engrave_offset = number(engrave_offset)
if bounds_low is None: if bounds_low is None:
# no bounds were given - we use the boundaries of the model # no bounds were given - we use the boundaries of the model
minx, miny, minz = (model.minx, model.miny, model.minz) minx, miny, minz = (model.minx, model.miny, model.minz)
else: else:
minx, miny, minz = bounds_low minx, miny, minz = [number(value) for value in bounds_low]
if bounds_high is None: if bounds_high is None:
# no bounds were given - we use the boundaries of the model # no bounds were given - we use the boundaries of the model
maxx, maxy, maxz = (model.maxx, model.maxy, model.maxz) maxx, maxy, maxz = (model.maxx, model.maxy, model.maxz)
else: else:
maxx, maxy, maxz = bounds_high maxx, maxy, maxz = [number(value) for value in bounds_high]
# trimesh model or contour model? # trimesh model or contour model?
if isinstance(model, pycam.Geometry.Model.Model): if isinstance(model, pycam.Geometry.Model.Model):
# trimesh model # trimesh model
...@@ -136,7 +141,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -136,7 +141,7 @@ def generate_toolpath(model, tool_settings=None,
trimesh_model = pycam.Geometry.Model.Model() trimesh_model = pycam.Geometry.Model.Model()
contour_model = model contour_model = model
# material allowance is ignored for engraving # material allowance is ignored for engraving
material_allowance = 0.0 material_allowance = 0
# create the grid model if requested # create the grid model if requested
if (((not support_grid_distance_x is None) \ if (((not support_grid_distance_x is None) \
or (not support_grid_distance_y is None)) \ or (not support_grid_distance_y is None)) \
...@@ -220,7 +225,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -220,7 +225,7 @@ def generate_toolpath(model, tool_settings=None,
if (overlap < 0) or (overlap >= 1): if (overlap < 0) or (overlap >= 1):
return "Invalid overlap value (%f): should be greater or equal 0 " \ return "Invalid overlap value (%f): should be greater or equal 0 " \
+ "and lower than 1" + "and lower than 1"
effective_toolradius = tool_settings["tool_radius"] * (1.0 - overlap) effective_toolradius =number(tool_settings["tool_radius"]) * (1 - overlap)
if path_generator == "DropCutter": if path_generator == "DropCutter":
if direction == "x": if direction == "x":
direction_param = 0 direction_param = 0
...@@ -230,6 +235,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -230,6 +235,7 @@ def generate_toolpath(model, tool_settings=None,
return "Invalid direction value (%s): not one of %s" \ return "Invalid direction value (%s): not one of %s" \
% (direction, DIRECTIONS) % (direction, DIRECTIONS)
if safety_height < maxz: if safety_height < maxz:
print "%s / %s / %s / %s" % (safety_height, maxz, type(safety_height), type(maxz))
return ("Safety height (%.4f) is within the bounding box height " \ return ("Safety height (%.4f) is within the bounding box height " \
+ "(%.4f) - this can cause collisions of the tool with " \ + "(%.4f) - this can cause collisions of the tool with " \
+ "the material.") % (safety_height, maxz) + "the material.") % (safety_height, maxz)
......
...@@ -24,6 +24,7 @@ from pycam.Geometry.Point import Point ...@@ -24,6 +24,7 @@ from pycam.Geometry.Point import Point
from pycam.Geometry.Line import Line from pycam.Geometry.Line import Line
from pycam.Geometry.Triangle import Triangle from pycam.Geometry.Triangle import Triangle
from pycam.Geometry.Model import Model from pycam.Geometry.Model import Model
from pycam.Geometry.utils import number
def _add_cuboid_to_model(minx, maxx, miny, maxy, minz, maxz): def _add_cuboid_to_model(minx, maxx, miny, maxy, minz, maxz):
...@@ -88,16 +89,21 @@ def get_support_grid_locations(minx, maxx, miny, maxy, dist_x, dist_y, ...@@ -88,16 +89,21 @@ def get_support_grid_locations(minx, maxx, miny, maxy, dist_x, dist_y,
# remove lines that are out of range (e.g. due to a huge offset) # remove lines that are out of range (e.g. due to a huge offset)
lines = [line for line in lines if min_value < line < max_value] lines = [line for line in lines if min_value < line < max_value]
return lines return lines
center_x = (maxx + minx) / 2.0 + offset_x # convert all inputs to the type defined in "number"
center_y = (maxy + miny) / 2.0 + offset_y dist_x = number(dist_x)
dist_y = number(dist_y)
offset_x = number(offset_x)
offset_y = number(offset_y)
center_x = (maxx + minx) / 2 + offset_x
center_y = (maxy + miny) / 2 + offset_y
lines_x = get_lines(center_x, dist_x, minx, maxx) lines_x = get_lines(center_x, dist_x, minx, maxx)
lines_y = get_lines(center_y, dist_y, miny, maxy) lines_y = get_lines(center_y, dist_y, miny, maxy)
if adjustments_x: if adjustments_x:
for index in range(min(len(lines_x), len(adjustments_x))): for index in range(min(len(lines_x), len(adjustments_x))):
lines_x[index] += adjustments_x[index] lines_x[index] += number(adjustments_x[index])
if adjustments_y: if adjustments_y:
for index in range(min(len(lines_y), len(adjustments_y))): for index in range(min(len(lines_y), len(adjustments_y))):
lines_y[index] += adjustments_y[index] lines_y[index] += number(adjustments_y[index])
return lines_x, lines_y return lines_x, lines_y
def get_support_grid(minx, maxx, miny, maxy, z_plane, dist_x, dist_y, thickness, def get_support_grid(minx, maxx, miny, maxy, z_plane, dist_x, dist_y, thickness,
...@@ -107,8 +113,11 @@ def get_support_grid(minx, maxx, miny, maxy, z_plane, dist_x, dist_y, thickness, ...@@ -107,8 +113,11 @@ def get_support_grid(minx, maxx, miny, maxy, z_plane, dist_x, dist_y, thickness,
dist_y, offset_x, offset_y, adjustments_x, adjustments_y) dist_y, offset_x, offset_y, adjustments_x, adjustments_y)
# create all x grid lines # create all x grid lines
grid_model = Model() grid_model = Model()
# convert all inputs to "number"
thickness = number(thickness)
height = number(height)
# helper variables # helper variables
thick_half = thickness / 2.0 thick_half = thickness / 2
length_extension = max(thickness, height) length_extension = max(thickness, height)
for line_x in lines_x: for line_x in lines_x:
# we make the grid slightly longer (by thickness) than necessary # we make the grid slightly longer (by thickness) than necessary
......
...@@ -23,6 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -23,6 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
__all__ = ["simplify_toolpath", "ToolPathList", "ToolPath", "Generator"] __all__ = ["simplify_toolpath", "ToolPathList", "ToolPath", "Generator"]
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import number
import pycam.Utils.log import pycam.Utils.log
import random import random
import os import os
...@@ -113,7 +114,7 @@ class ToolPath: ...@@ -113,7 +114,7 @@ class ToolPath:
settings = self.toolpath_settings settings = self.toolpath_settings
if start_position is None: if start_position is None:
start_position = Point(0, 0, 0) start_position = Point(0, 0, 0)
feedrate = settings.get_tool_settings()["feedrate"] feedrate = number(settings.get_tool_settings()["feedrate"])
result = {} result = {}
result["time"] = 0 result["time"] = 0
result["position"] = start_position result["position"] = start_position
...@@ -121,7 +122,7 @@ class ToolPath: ...@@ -121,7 +122,7 @@ class ToolPath:
result["time"] += new_pos.sub(result["position"]).norm / feedrate result["time"] += new_pos.sub(result["position"]).norm / feedrate
result["position"] = new_pos result["position"] = new_pos
# move to safey height at the starting position # move to safey height at the starting position
safety_height = settings.get_process_settings()["safety_height"] safety_height = number(settings.get_process_settings()["safety_height"])
move(Point(start_position.x, start_position.y, safety_height)) move(Point(start_position.x, start_position.y, safety_height))
for path in self.get_path(): for path in self.get_path():
# go to safety height (horizontally from the previous x/y location) # go to safety height (horizontally from the previous x/y location)
...@@ -214,14 +215,14 @@ class Bounds: ...@@ -214,14 +215,14 @@ class Bounds:
raise ValueError, "lower bounds should be supplied as a " \ raise ValueError, "lower bounds should be supplied as a " \
+ "tuple/list of 3 items - but %d were given" % len(low) + "tuple/list of 3 items - but %d were given" % len(low)
else: else:
self.bounds_low = list(low[:]) self.bounds_low = [number(value) for value in low]
if not high is None: if not high is None:
if len(high) != 3: if len(high) != 3:
raise ValueError, "upper bounds should be supplied as a " \ raise ValueError, "upper bounds should be supplied as a " \
+ "tuple/list of 3 items - but %d were given" \ + "tuple/list of 3 items - but %d were given" \
% len(high) % len(high)
else: else:
self.bounds_high = list(high[:]) self.bounds_high = [number(value) for value in high]
def get_absolute_limits(self, reference=None): def get_absolute_limits(self, reference=None):
""" calculate the current absolute limits of the Bounds instance """ calculate the current absolute limits of the Bounds instance
...@@ -262,8 +263,8 @@ class Bounds: ...@@ -262,8 +263,8 @@ class Bounds:
high[index] = ref_high[index] + self.bounds_high[index] high[index] = ref_high[index] + self.bounds_high[index]
elif self.bounds_type == Bounds.TYPE_CUSTOM: elif self.bounds_type == Bounds.TYPE_CUSTOM:
for index in range(3): for index in range(3):
low[index] = self.bounds_low[index] low[index] = number(self.bounds_low[index])
high[index] = self.bounds_high[index] high[index] = number(self.bounds_high[index])
else: else:
# this should not happen # this should not happen
raise NotImplementedError, "the function 'get_absolute_limits' is" \ raise NotImplementedError, "the function 'get_absolute_limits' is" \
......
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