From: daid Date: Mon, 2 Dec 2013 13:02:59 +0000 (+0100) Subject: Allow tight packing of "one at a time" objects without causing head collisions. X-Git-Tag: 14.01~45 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=a9def49512d78528d981f08c0f0ba34c5d2cab48;p=cura.git Allow tight packing of "one at a time" objects without causing head collisions. --- diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py index 021947cd..370b1546 100644 --- a/Cura/gui/sceneView.py +++ b/Cura/gui/sceneView.py @@ -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) diff --git a/Cura/util/mesh.py b/Cura/util/mesh.py index cf196d4a..220a590f 100644 --- a/Cura/util/mesh.py +++ b/Cura/util/mesh.py @@ -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]] diff --git a/Cura/util/objectScene.py b/Cura/util/objectScene.py index 73df0c0e..ab9319ab 100644 --- a/Cura/util/objectScene.py +++ b/Cura/util/objectScene.py @@ -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()) diff --git a/Cura/util/polygon.py b/Cura/util/polygon.py index 8da33639..a6592fec 100644 --- a/Cura/util/polygon.py +++ b/Cura/util/polygon.py @@ -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)