chiark / gitweb /
Allow tight packing of "one at a time" objects without causing head collisions.
authordaid <daid303@gmail.com>
Mon, 2 Dec 2013 13:02:59 +0000 (14:02 +0100)
committerdaid <daid303@gmail.com>
Mon, 2 Dec 2013 13:02:59 +0000 (14:02 +0100)
Cura/gui/sceneView.py
Cura/util/mesh.py
Cura/util/objectScene.py
Cura/util/polygon.py

index 021947cdfe4d90bfc5d76b444d07b1774ca4ddad..370b1546252dd8aa1bf9578046ef9807931b236e 100644 (file)
@@ -1188,7 +1188,7 @@ void main(void)
                                        glVertex3f(p[0], p[1], 0)
                                glEnd()
                                glBegin(GL_TRIANGLE_FAN)
-                               for p in self._selectedObj._headAreaHull[::-1]:
+                               for p in self._selectedObj._headAreaMinHull[::-1]:
                                        glVertex3f(p[0], p[1], 0)
                                glEnd()
                                glDepthMask(True)
index cf196d4a8eba80750a841814e40bccf37c0106da..220a590f63afa583ced3f366b4e0f4f405fa9199 100644 (file)
@@ -30,8 +30,10 @@ class printableObject(object):
                self._boundaryHull = None
                self._printAreaExtend = numpy.array([[-1,-1],[ 1,-1],[ 1, 1],[-1, 1]], numpy.float32)
                self._headAreaExtend = numpy.array([[-1,-1],[ 1,-1],[ 1, 1],[-1, 1]], numpy.float32)
+               self._headMinSize = numpy.array([1, 1], numpy.float32)
                self._printAreaHull = None
                self._headAreaHull = None
+               self._headAreaMinHull = None
 
                self._loadAnim = None
 
@@ -104,7 +106,7 @@ class printableObject(object):
 
                self._boundaryHull = polygon.minkowskiHull((hull.astype(numpy.float32) - self._drawOffset[0:2]), numpy.array([[-1,-1],[-1,1],[1,1],[1,-1]],numpy.float32))
                self._printAreaHull = polygon.minkowskiHull(self._boundaryHull, self._printAreaExtend)
-               self._headAreaHull = polygon.minkowskiHull(self._printAreaHull, self._headAreaExtend)
+               self.setHeadArea(self._headAreaExtend, self._headMinSize)
 
        def getName(self):
                return self._name
@@ -131,11 +133,17 @@ class printableObject(object):
        def setPrintAreaExtends(self, poly):
                self._printAreaExtend = poly
                self._printAreaHull = polygon.minkowskiHull(self._boundaryHull, self._printAreaExtend)
-               self._headAreaHull = polygon.minkowskiHull(self._printAreaHull, self._headAreaExtend)
 
-       def setHeadArea(self, poly):
+               self.setHeadArea(self._headAreaExtend, self._headMinSize)
+
+       def setHeadArea(self, poly, minSize):
                self._headAreaExtend = poly
+               self._headMinSize = minSize
                self._headAreaHull = polygon.minkowskiHull(self._printAreaHull, self._headAreaExtend)
+               pMin = numpy.min(self._printAreaHull, 0) - self._headMinSize
+               pMax = numpy.max(self._printAreaHull, 0) + self._headMinSize
+               square = numpy.array([pMin, [pMin[0], pMax[1]], pMax, [pMax[0], pMin[1]]], numpy.float32)
+               self._headAreaMinHull = polygon.clipConvex(self._headAreaHull, square)
 
        def mirror(self, axis):
                matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
index 73df0c0e39e333c5e096904fdcaeb56905d0623a..ab9319abdb1049f7870f135a97e9a386aefcf480 100644 (file)
@@ -11,9 +11,8 @@ class _objectOrder(object):
                self.todo = todo
 
 class _objectOrderFinder(object):
-       def __init__(self, scene, offset, leftToRight, frontToBack, gantryHeight):
+       def __init__(self, scene, leftToRight, frontToBack, gantryHeight):
                self._scene = scene
-               self._offset = offset - numpy.array([0.1,0.1])
                self._objs = scene.objects()
                self._leftToRight = leftToRight
                self._frontToBack = frontToBack
@@ -125,14 +124,11 @@ class Scene(object):
 
                headArea = numpy.array([[-xMin,-yMin],[ xMax,-yMin],[ xMax, yMax],[-xMin, yMax]], numpy.float32)
                for obj in self._objectList:
-                       obj.setHeadArea(headArea)
+                       obj.setHeadArea(headArea, self._headSizeOffsets)
 
        def setExtruderOffset(self, extruderNr, offsetX, offsetY):
                self._extruderOffset[extruderNr] = numpy.array([offsetX, offsetY], numpy.float32)
 
-       def getObjectExtend(self):
-               return self._sizeOffsets + self._headSizeOffsets
-
        def objects(self):
                return self._objectList
 
@@ -190,7 +186,7 @@ class Scene(object):
 
        def printOrder(self):
                if self._oneAtATime:
-                       order = _objectOrderFinder(self, self._headSizeOffsets + self._sizeOffsets, self._leftToRight, self._frontToBack, self._gantryHeight).order
+                       order = _objectOrderFinder(self, self._leftToRight, self._frontToBack, self._gantryHeight).order
                else:
                        order = None
                return order
@@ -200,7 +196,10 @@ class Scene(object):
                        for b in self._objectList:
                                if a == b:
                                        continue
-                               v = polygon.polygonCollisionPushVector(a._boundaryHull + a.getPosition(), b._boundaryHull + b.getPosition())
+                               if self._oneAtATime:
+                                       v = polygon.polygonCollisionPushVector(a._headAreaMinHull + a.getPosition(), b._boundaryHull + b.getPosition())
+                               else:
+                                       v = polygon.polygonCollisionPushVector(a._boundaryHull + a.getPosition(), b._boundaryHull + b.getPosition())
                                if type(v) is bool:
                                        continue
                                a.setPosition(a.getPosition() + v / 2.0)
@@ -213,7 +212,7 @@ class Scene(object):
                if a == b:
                        return False
                if self._oneAtATime:
-                       return polygon.polygonCollision(a._headAreaHull + a.getPosition(), b._boundaryHull + b.getPosition())
+                       return polygon.polygonCollision(a._headAreaMinHull + a.getPosition(), b._boundaryHull + b.getPosition())
                else:
                        return polygon.polygonCollision(a._boundaryHull + a.getPosition(), b._boundaryHull + b.getPosition())
 
index 8da33639bf69da041529efa23525ea80fb0d7c40..a6592fec5a056c11c38710667b8f28e77051ed35 100644 (file)
@@ -118,6 +118,38 @@ def polygonCollisionPushVector(polyA, polyB):
                if size < retSize:
                        ret = normal * -(size + 0.1)
                        retSize = size
-       #ret = ret[::-1]
-       #ret[1] = -ret[1]
        return ret
+
+def isLeft(a, b, c):
+       return ((b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0])) > 0
+
+def lineLineIntersection(p0, p1, p2, p3):
+       A1 = p1[1] - p0[1]
+       B1 = p0[0] - p1[0]
+       C1 = A1*p0[0] + B1*p0[1]
+
+       A2 = p3[1] - p2[1]
+       B2 = p2[0] - p3[0]
+       C2 = A2 * p2[0] + B2 * p2[1]
+
+       det = A1*B2 - A2*B1
+       if det == 0:
+               return p0
+       return [(B2*C1 - B1*C2)/det, (A1 * C2 - A2 * C1) / det]
+
+def clipConvex(poly0, poly1):
+       res = poly0
+       for p1idx in xrange(0, len(poly1)):
+               src = res
+               res = []
+               p0 = poly1[p1idx-1]
+               p1 = poly1[p1idx]
+               for n in xrange(0, len(src)):
+                       p = src[n]
+                       if not isLeft(p0, p1, p):
+                               if isLeft(p0, p1, src[n-1]):
+                                       res.append(lineLineIntersection(p0, p1, src[n-1], p))
+                               res.append(p)
+                       elif not isLeft(p0, p1, src[n-1]):
+                               res.append(lineLineIntersection(p0, p1, src[n-1], p))
+       return numpy.array(res, numpy.float32)