Commit 263a23f0 authored by sumpfralle's avatar sumpfralle

unify min/max properties for geometry objects

calculate all properties during instanciation (not on demand)


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@561 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent d1e456b7
......@@ -39,10 +39,10 @@ class BaseCutter(object):
self.id = BaseCutter.id
BaseCutter.id += 1
self.radius = radius
self.radiussq = radius*radius
self.radiussq = radius ** 2
self.required_distance = 0
self.distance_radius = self.radius
self.distance_radiussq = self.distance_radius * self.distance_radius
self.distance_radiussq = self.distance_radius ** 2
# self.minx, self.maxx, self.miny and self.maxy are defined as
# properties below
self.shape = {}
......@@ -98,20 +98,20 @@ class BaseCutter(object):
def drop(self, triangle):
# check bounding box collision
if self.minx > triangle.maxx():
if self.minx > triangle.maxx:
return None
if self.maxx < triangle.minx():
if self.maxx < triangle.minx:
return None
if self.miny > triangle.maxy():
if self.miny > triangle.maxy:
return None
if self.maxy < triangle.miny():
if self.maxy < triangle.miny:
return None
# check bounding circle collision
c = triangle.center()
c = triangle.center
if (c.x - self.location.x) ** 2 + (c.y - self.location.y) ** 2 \
> (self.distance_radiussq + 2 * self.distance_radius \
* triangle.radius() + triangle.radiussq()):
* triangle.radius + triangle.radiussq):
return None
(cl, d)= self.intersect(BaseCutter.vertical, triangle)
......@@ -121,22 +121,22 @@ class BaseCutter(object):
""" TODO: this function is never used - remove it? """
# check bounding box collision
if dx == 0:
if self.miny > triangle.maxy():
if self.miny > triangle.maxy:
return None
if self.maxy < triangle.miny():
if self.maxy < triangle.miny:
return None
if dy == 0:
if self.minx > triangle.maxx():
if self.minx > triangle.maxx:
return None
if self.maxx < triangle.minx():
if self.maxx < triangle.minx:
return None
if triangle.maxz() < self.location.z:
if triangle.maxz < self.location.z:
return None
# check bounding sphere collision
c = triangle.center()
c = triangle.center
d = (c.x - self.location.x) * dy -(c.y - self.location.y) * dx
t = self.radius + triangle.radius()
t = self.radius + triangle.radius
if abs(d) > t:
return None
......
......@@ -175,8 +175,8 @@ class CylindricalCutter(BaseCutter):
(cl, ccp, cp, l) = self.intersect_circle_line(direction, edge)
if cp:
# check if the contact point is between the endpoints
m = cp.sub(edge.p1).dot(edge.dir())
if (m < 0) or (m > edge.len()):
m = cp.sub(edge.p1).dot(edge.dir)
if (m < 0) or (m > edge.len):
return (None, INFINITE)
return (cl, l)
......@@ -208,8 +208,8 @@ class CylindricalCutter(BaseCutter):
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge)
if not ccp:
return (None, INFINITE)
m = cp.sub(edge.p1).dot(edge.dir())
if (m < 0) or (m > edge.len()):
m = cp.sub(edge.p1).dot(edge.dir)
if (m < 0) or (m > edge.len):
return (None, INFINITE)
if ccp.z < self.center.z:
return (None, INFINITE)
......
......@@ -188,7 +188,7 @@ class SphericalCutter(BaseCutter):
# check if the contact point is between the endpoints
d = edge.p2.sub(edge.p1)
m = cp.sub(edge.p1).dot(d)
if (m < 0) or (m > d.normsq()):
if (m < 0) or (m > d.normsq):
return (None, INFINITE)
return (cl, l)
......@@ -220,8 +220,8 @@ class SphericalCutter(BaseCutter):
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge)
if not ccp:
return (None, INFINITE)
m = cp.sub(edge.p1).dot(edge.dir())
if (m < 0) or (m > edge.len()):
m = cp.sub(edge.p1).dot(edge.dir)
if (m < 0) or (m > edge.len):
return (None, INFINITE)
if ccp.z < self.center.z:
return (None, INFINITE)
......@@ -299,7 +299,7 @@ class SphericalCutter(BaseCutter):
def drop_bis(self, triangle):
""" TODO: this function is never called - remove it? """
n = triangle.normal()
n = triangle.normal
if abs(n.dot(self.axis)) < epsilon:
d = triangle.p1.sub(self.center).dot(n)
if abs(d) >= self.radius - epsilon:
......
......@@ -151,7 +151,7 @@ class ToroidalCutter(BaseCutter):
min_m = 0
min_l = INFINITE
min_cl = None
scale = int(edge.len() / self.distance_minorradius * 2)
scale = int(edge.len / self.distance_minorradius * 2)
scale = max(3, scale)
for i in range(scale + 1):
m = float(i) / scale
......@@ -208,8 +208,8 @@ class ToroidalCutter(BaseCutter):
if ccp and ccp.z < self.center.z:
return (None, INFINITE)
if ccp:
m = cp.sub(edge.p1).dot(edge.dir())
if (m < 0) or (m > edge.len()):
m = cp.sub(edge.p1).dot(edge.dir)
if (m < 0) or (m > edge.len):
return (None, INFINITE)
return (cl, l)
......@@ -254,8 +254,8 @@ class ToroidalCutter(BaseCutter):
(cl, ccp, cp, l) = self.intersect_circle_line(direction, edge)
if cp:
# check if the contact point is between the endpoints
m = cp.sub(edge.p1).dot(edge.dir())
if (m < 0) or (m > edge.len()):
m = cp.sub(edge.p1).dot(edge.dir)
if (m < 0) or (m > edge.len):
return (None, INFINITE)
return (cl, l)
......
......@@ -51,7 +51,7 @@ class STLExporter:
for line in self.comment.split(self.linesep):
yield(";%s" % line)
for tr in self.model.triangles():
norm = tr.normal().normalize()
norm = tr.normal.normalized()
yield "facet normal %f %f %f" % (norm.x, norm.y, norm.z)
yield " outer loop"
for p in (tr.p1, tr.p2, tr.p3):
......
This diff is collapsed.
......@@ -121,8 +121,7 @@ def get_rotation_matrix_from_to(v_orig, v_dest):
# destination vectors.
rot_axis = Point(v_orig[1] * v_dest[2] - v_orig[2] * v_dest[1],
v_orig[2] * v_dest[0] - v_orig[0] * v_dest[2],
v_orig[0] * v_dest[1] - v_orig[1] * v_dest[0])
rot_axis.normalize()
v_orig[0] * v_dest[1] - v_orig[1] * v_dest[0]).normalized()
# get the rotation matrix
# see http://www.fastgraph.com/makegames/3drotation/
c = math.cos(rot_angle)
......
......@@ -92,26 +92,20 @@ class BaseModel(TransformableContainer):
+ "support the 'export' function.") % str(type(self)))
def _update_limits(self, item):
if callable(item.minx):
minx, miny, minz = item.minx(), item.miny(), item.minz()
maxx, maxy, maxz = item.maxx(), item.maxy(), item.maxz()
else:
minx, miny, minz = item.minx, item.miny, item.minz
maxx, maxy, maxz = item.maxx, item.maxy, item.maxz
if self.minx is None:
self.minx = minx
self.miny = miny
self.minz = minz
self.maxx = maxx
self.maxy = maxy
self.maxz = maxz
self.minx = item.minx
self.miny = item.miny
self.minz = item.minz
self.maxx = item.maxx
self.maxy = item.maxy
self.maxz = item.maxz
else:
self.minx = min(self.minx, minx)
self.miny = min(self.miny, miny)
self.minz = min(self.minz, minz)
self.maxx = max(self.maxx, maxx)
self.maxy = max(self.maxy, maxy)
self.maxz = max(self.maxz, maxz)
self.minx = min(self.minx, item.minx)
self.miny = min(self.miny, item.miny)
self.minz = min(self.minz, item.minz)
self.maxx = max(self.maxx, item.maxx)
self.maxy = max(self.maxy, item.maxy)
self.maxz = max(self.maxz, item.maxz)
def append(self, item):
self._update_limits(item)
......
......@@ -35,9 +35,9 @@ class Plane:
return "Plane<%s,%s>" % (self.p, self.n)
def intersect_point(self, direction, point):
if direction.norm() != 1:
if direction.norm != 1:
# calculations will go wrong, if the direction is not a unit vector
direction = Point(direction.x, direction.y, direction.z).normalize()
direction = Point(direction.x, direction.y, direction.z).normalized()
denom = self.n.dot(direction)
if denom == 0:
return (None, INFINITE)
......
......@@ -36,8 +36,7 @@ class Point:
self.x = float(x)
self.y = float(y)
self.z = float(z)
self._norm = None
self._normsq = None
self.reset_cache()
def __repr__(self):
return "Point%d<%g,%g,%g>" % (self.id, self.x, self.y, self.z)
......@@ -74,13 +73,14 @@ class Point:
self.reset_cache()
def reset_cache(self):
self._norm = None
self._normsq = None
self.normsq = self.dot(self)
self.norm = math.sqrt(self.normsq)
def mul(self, c):
return Point(self.x * c, self.y * c, self.z * c)
def div(self, c):
c = float(c)
return Point(self.x / c, self.y / c, self.z / c)
def add(self, p):
......@@ -96,23 +96,10 @@ class Point:
return Point(self.y * p.z - p.y * self.z, p.x * self.z - self.x * p.z,
self.x * p.y - p.x * self.y)
def normsq(self):
if self._normsq is None:
self._normsq = self.dot(self)
return self._normsq
def norm(self):
if self._norm is None:
self._norm = math.sqrt(self.normsq())
return self._norm
def normalize(self):
n = self.norm()
if n != 0:
self.x /= n
self.y /= n
self.z /= n
self._norm = 1.0
self._normsq = 1.0
return self
def normalized(self):
n = self.norm
if n == 0:
return None
else:
return Point(self.x / n, self.y / n, self.z / n)
This diff is collapsed.
......@@ -61,8 +61,7 @@ def intersect_lines(xl, zl, nxl, nzl, xm, zm, nxm, nzm):
def intersect_cylinder_point(center, axis, radius, radiussq, direction, point):
# take a plane along direction and axis
n = direction.cross(axis)
n.normalize()
n = direction.cross(axis).normalized()
# distance of the point to this plane
d = n.dot(point) - n.dot(center)
if abs(d) > radius:
......@@ -77,14 +76,14 @@ def intersect_cylinder_point(center, axis, radius, radiussq, direction, point):
return (ccp, point, -l)
def intersect_cylinder_line(center, axis, radius, radiussq, direction, edge):
d = edge.dir()
d = edge.dir
# take a plane throught the line and along the cylinder axis (1)
n = d.cross(axis)
if n.normsq() == 0:
if n.norm == 0:
# no contact point, but should check here if cylinder *always*
# intersects line...
return (None, None, INFINITE)
n.normalize()
n = n.normalized()
# the contact line between the cylinder and this plane (1)
# is where the surface normal is perpendicular to the plane
# so line := ccl + \lambda * axis
......@@ -94,11 +93,11 @@ def intersect_cylinder_line(center, axis, radius, radiussq, direction, edge):
ccl = center.add(n.mul(radius))
# now extrude the contact line along the direction, this is a plane (2)
n2 = direction.cross(axis)
if n2.normsq() == 0:
if n2.norm == 0:
# no contact point, but should check here if cylinder *always*
# intersects line...
return (None, None, INFINITE)
n2.normalize()
n2 = n2.normalized()
plane1 = Plane(ccl, n2)
# intersect this plane with the line, this gives us the contact point
(cp, l) = plane1.intersect_point(d, edge.p1)
......@@ -115,20 +114,20 @@ def intersect_cylinder_line(center, axis, radius, radiussq, direction, edge):
def intersect_circle_plane(center, radius, direction, triangle):
# let n be the normal to the plane
n = triangle.normal()
n = triangle.normal
if n.dot(direction) == 0:
return (None, None, INFINITE)
# project onto z=0
n2 = Point(n.x, n.y, 0)
if n2.normsq() == 0:
(cp, d) = triangle.plane().intersect_point(direction, center)
if n2.norm == 0:
(cp, d) = triangle.plane.intersect_point(direction, center)
ccp = cp.sub(direction.mul(d))
return (ccp, cp, d)
n2.normalize()
n2 = n2.normalized()
# the cutter contact point is on the circle, where the surface normal is n
ccp = center.add(n2.mul(-radius))
# intersect the plane with a line through the contact point
(cp, d) = triangle.plane().intersect_point(direction, ccp)
(cp, d) = triangle.plane.intersect_point(direction, ccp)
return (ccp, cp, d)
def intersect_circle_point(center, axis, radius, radiussq, direction, point):
......@@ -137,13 +136,13 @@ def intersect_circle_point(center, axis, radius, radiussq, direction, point):
# intersect with line gives ccp
(ccp, l) = plane.intersect_point(direction, point)
# check if inside circle
if ccp and (center.sub(ccp).normsq() <= radiussq):
if ccp and (center.sub(ccp).normsq <= radiussq):
return (ccp, point, -l)
return (None, None, INFINITE)
def intersect_circle_line(center, axis, radius, radiussq, direction, edge):
# make a plane by sliding the line along the direction (1)
d = edge.dir()
d = edge.dir
if d.dot(axis) == 0:
if direction.dot(axis) == 0:
return (None, None, INFINITE)
......@@ -151,7 +150,7 @@ def intersect_circle_line(center, axis, radius, radiussq, direction, edge):
(p1, l) = plane.intersect_point(direction, edge.p1)
(p2, l) = plane.intersect_point(direction, edge.p2)
pc = Line(p1, p2).closest_point(center)
d_sq = pc.sub(center).normsq()
d_sq = pc.sub(center).normsq
if d_sq > radiussq:
return (None, None, INFINITE)
a = sqrt(radiussq - d_sq)
......@@ -170,11 +169,11 @@ def intersect_circle_line(center, axis, radius, radiussq, direction, edge):
cp = pc.sub(direction.mul(l))
return (ccp, cp, -l)
n = d.cross(direction)
if n.normsq() == 0:
if n.norm == 0:
# no contact point, but should check here if circle *always* intersects
# line...
return (None, None, INFINITE)
n.normalize()
n = n.normalized()
# take a plane through the base
plane = Plane(center, axis)
# intersect base with line
......@@ -183,14 +182,14 @@ def intersect_circle_line(center, axis, radius, radiussq, direction, edge):
return (None, None, INFINITE)
# intersection of 2 planes: lp + \lambda v
v = axis.cross(n)
if v.normsq() == 0:
if v.norm == 0:
return (None, None, INFINITE)
v.normalize()
v = v.normalized()
# take plane through intersection line and parallel to axis
n2 = v.cross(axis)
if n2.normsq() == 0:
if n2.norm == 0:
return (None, None, INFINITE)
n2.normalize()
n2 = n2.normalized()
# distance from center to this plane
dist = n2.dot(center) - n2.dot(lp)
distsq = dist * dist
......@@ -207,7 +206,7 @@ def intersect_circle_line(center, axis, radius, radiussq, direction, edge):
def intersect_sphere_plane(center, radius, direction, triangle):
# let n be the normal to the plane
n = triangle.normal()
n = triangle.normal
if n.dot(direction) == 0:
return (None, None, INFINITE)
# the cutter contact point is on the sphere, where the surface normal is n
......@@ -216,7 +215,7 @@ def intersect_sphere_plane(center, radius, direction, triangle):
else:
ccp = center.add(n.mul(radius))
# intersect the plane with a line through the contact point
(cp, d) = triangle.plane().intersect_point(direction, ccp)
(cp, d) = triangle.plane.intersect_point(direction, ccp)
return (ccp, cp, d)
def intersect_sphere_point(center, radius, radiussq, direction, point):
......@@ -226,9 +225,9 @@ def intersect_sphere_point(center, radius, radiussq, direction, point):
# (2) (x-x_0)^2 = R^2
# (1) in (2) gives a quadratic in \lambda
p0_x0 = center.sub(point)
a = direction.normsq()
a = direction.normsq
b = 2 * p0_x0.dot(direction)
c = p0_x0.normsq() - radiussq
c = p0_x0.normsq - radiussq
d = b * b - 4 * a * c
if d < 0:
return (None, None, INFINITE)
......@@ -242,13 +241,13 @@ def intersect_sphere_point(center, radius, radiussq, direction, point):
def intersect_sphere_line(center, radius, radiussq, direction, edge):
# make a plane by sliding the line along the direction (1)
d = edge.dir()
d = edge.dir
n = d.cross(direction)
if n.normsq() == 0:
if n.norm == 0:
# no contact point, but should check here if sphere *always* intersects
# line...
return (None, None, INFINITE)
n.normalize()
n = n.normalized()
# calculate the distance from the sphere center to the plane
dist = - center.dot(n) - edge.p1.dot(n)
......@@ -260,8 +259,7 @@ def intersect_sphere_line(center, radius, radiussq, direction, edge):
# find the center on the circle closest to this plane
# which means the other component is perpendicular to this plane (2)
n2 = n.cross(d)
n2.normalize()
n2 = n.cross(d).normalized()
# the contact point is on a big circle through the sphere...
dist2 = sqrt(radiussq - dist * dist)
......@@ -277,7 +275,7 @@ def intersect_sphere_line(center, radius, radiussq, direction, edge):
def intersect_torus_plane(center, axis, majorradius, minorradius, direction,
triangle):
# take normal to the plane
n = triangle.normal()
n = triangle.normal
if n.dot(direction) == 0:
return (None, None, INFINITE)
if n.dot(axis) == 1:
......@@ -286,14 +284,13 @@ def intersect_torus_plane(center, axis, majorradius, minorradius, direction,
b = n.mul(-1)
z = axis
a = b.sub(z.mul(z.dot(b)))
a_sq = a.normsq()
a_sq = a.normsq
if a_sq <= 0:
return (None, None, INFINITE)
a = a.div(sqrt(a_sq))
ccp = center.add(a.mul(majorradius)).add(b.mul(minorradius))
# find intersection with plane
plane = triangle.plane()
(cp, l) = plane.intersect_point(direction, ccp)
(cp, l) = triangle.plane.intersect_point(direction, ccp)
return (ccp, cp, l)
def intersect_torus_point(center, axis, majorradius, minorradius, majorradiussq,
......
......@@ -91,7 +91,7 @@ class Camera:
dimz = s.get("maxz") - s.get("minz")
max_dim = max(max(dimx, dimy), dimz)
distv = Point(v["distance"][0], v["distance"][1],
v["distance"][2]).normalize()
v["distance"][2]).normalized()
# The multiplier "2.0" is based on: sqrt(2) + margin -- the squre root
# makes sure, that the the diagonal fits.
distv = distv.mul((max_dim * 2.0) / math.sin(v["fovy"]/2))
......@@ -216,8 +216,8 @@ class Camera:
# Calculate the proportion of each model axis according to the x axis of
# the screen.
distv = self.view["distance"]
distv = Point(distv[0], distv[1], distv[2]).normalize()
factors_x = distv.cross(Point(v_up[0], v_up[1], v_up[2])).normalize()
distv = Point(distv[0], distv[1], distv[2]).normalized()
factors_x = distv.cross(Point(v_up[0], v_up[1], v_up[2])).normalized()
factors_x = (factors_x.x, factors_x.y, factors_x.z)
return (factors_x, factors_y)
......
......@@ -79,8 +79,8 @@ class DXFParser:
current_group = []
groups.append(current_group)
def get_distance_between_groups(group1, group2):
forward = group1[-1].p2.sub(group2[0].p1).norm()
backward = group2[-1].p2.sub(group1[0].p1).norm()
forward = group1[-1].p2.sub(group2[0].p1).norm
backward = group2[-1].p2.sub(group1[0].p1).norm
return min(forward, backward)
remaining_groups = groups[:]
ordered_groups = []
......
......@@ -232,8 +232,7 @@ def ImportModel(filename, use_kdtree=True, program_locations=None):
m = endfacet.match(line)
if m:
if not n:
n = p3.sub(p1).cross(p2.sub(p1))
n.normalize()
n = p3.sub(p1).cross(p2.sub(p1)).normalized()
# make sure the points are in ClockWise order
dotcross = n.dot(p3.sub(p1).cross(p2.sub(p1)))
......
......@@ -106,13 +106,13 @@ class ZBuffer:
self.add_triangle(t)
def add_triangle(self, t):
minx = int((t.minx() - self.minx) / (self.maxx - self.minx) \
minx = int((t.minx - self.minx) / (self.maxx - self.minx) \
* self.xres) - 1
maxx = int((t.maxx() - self.minx) / (self.maxx - self.minx) \
maxx = int((t.maxx - self.minx) / (self.maxx - self.minx) \
* self.xres) + 1
miny = int((t.miny() - self.miny) / (self.maxy - self.miny) \
miny = int((t.miny - self.miny) / (self.maxy - self.miny) \
* self.yres) - 1
maxy = int((t.maxy() - self.miny) / (self.maxy - self.miny) \
maxy = int((t.maxy - self.miny) / (self.maxy - self.miny) \
* self.yres) + 2
if minx < 0:
minx = 0
......
......@@ -31,10 +31,8 @@ log = pycam.Utils.log.get_logger()
def _check_colinearity(p1, p2, p3):
v1 = p2.sub(p1)
v2 = p3.sub(p2)
v1.normalize()
v2.normalize()
v1 = p2.sub(p1).normalized()
v2 = p3.sub(p2).normalized()
# compare if the normalized distances between p1-p2 and p2-p3 are equal
return v1 == v2
......@@ -120,7 +118,7 @@ class ToolPath:
result["time"] = 0
result["position"] = start_position
def move(new_pos):
result["time"] += new_pos.sub(result["position"]).norm() / feedrate
result["time"] += new_pos.sub(result["position"]).norm / feedrate
result["position"] = new_pos
# move to safey height at the starting position
safety_height = settings.get_process_settings()["safety_height"]
......
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