chiark / gitweb /
Allow for odd shaped platforms and generalize the UM2 clip code into no-go zones.
authordaid <daid303@gmail.com>
Tue, 3 Dec 2013 10:33:00 +0000 (11:33 +0100)
committerdaid <daid303@gmail.com>
Tue, 3 Dec 2013 10:33:00 +0000 (11:33 +0100)
Cura/gui/sceneView.py
Cura/util/objectScene.py
Cura/util/polygon.py
Cura/util/profile.py

index e6e116a9296b723b2f4e4bc70dd78c7d2305c7cc..c7dbbb48baea1936ff24eb6e459534a677f0aba2 100644 (file)
@@ -56,6 +56,7 @@ class SceneView(openglGui.glGuiPanel):
                self._animView = None
                self._animZoom = None
                self._platformMesh = {}
+               self._platformTexture = None
                self._isSimpleMode = True
                self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
                self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
@@ -631,8 +632,7 @@ class SceneView(openglGui.glGuiPanel):
                self._objColors[1] = profile.getPreferenceColour('model_colour2')
                self._objColors[2] = profile.getPreferenceColour('model_colour3')
                self._objColors[3] = profile.getPreferenceColour('model_colour4')
-               self._scene.setMachineSize(self._machineSize)
-               self._scene.setHeadSize(profile.getMachineSettingFloat('extruder_head_size_min_x'), profile.getMachineSettingFloat('extruder_head_size_max_x'), profile.getMachineSettingFloat('extruder_head_size_min_y'), profile.getMachineSettingFloat('extruder_head_size_max_y'), profile.getMachineSettingFloat('extruder_head_size_height'))
+               self._scene.updateMachineDimensions()
 
                if self._selectedObj is not None:
                        scale = self._selectedObj.getScale()
@@ -1264,7 +1264,7 @@ void main(void)
                size = [profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')]
 
                machine = profile.getMachineSetting('machine_type')
-               if profile.getMachineSetting('machine_type').startswith('ultimaker'):
+               if machine.startswith('ultimaker'):
                        if machine not in self._platformMesh:
                                meshes = meshLoader.loadMeshes(resources.getPathForMesh(machine + '_platform.stl'))
                                if len(meshes) > 0:
@@ -1330,62 +1330,79 @@ void main(void)
                        glEnd()
 
                #Cornerpoints for big blue square
-               v0 = [ size[0] / 2, size[1] / 2, size[2]]
-               v1 = [ size[0] / 2,-size[1] / 2, size[2]]
-               v2 = [-size[0] / 2, size[1] / 2, size[2]]
-               v3 = [-size[0] / 2,-size[1] / 2, size[2]]
-               v4 = [ size[0] / 2, size[1] / 2, 0]
-               v5 = [ size[0] / 2,-size[1] / 2, 0]
-               v6 = [-size[0] / 2, size[1] / 2, 0]
-               v7 = [-size[0] / 2,-size[1] / 2, 0]
-
-               vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
-               glEnableClientState(GL_VERTEX_ARRAY)
-               glVertexPointer(3, GL_FLOAT, 3*4, vList)
+               v0 = [ size[0] / 2, size[1] / 2, size[2]]
+               v1 = [ size[0] / 2,-size[1] / 2, size[2]]
+               v2 = [-size[0] / 2, size[1] / 2, size[2]]
+               v3 = [-size[0] / 2,-size[1] / 2, size[2]]
+               v4 = [ size[0] / 2, size[1] / 2, 0]
+               v5 = [ size[0] / 2,-size[1] / 2, 0]
+               v6 = [-size[0] / 2, size[1] / 2, 0]
+               v7 = [-size[0] / 2,-size[1] / 2, 0]
+               #
+               vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
+               glEnableClientState(GL_VERTEX_ARRAY)
+               glVertexPointer(3, GL_FLOAT, 3*4, vList)
 
                glDepthMask(False)
-               glColor4ub(5, 171, 231, 64)
-               glDrawArrays(GL_QUADS, 0, 4)
-               glColor4ub(5, 171, 231, 96)
-               glDrawArrays(GL_QUADS, 4, 8)
+               # glColor4ub(5, 171, 231, 64)
+               # glDrawArrays(GL_QUADS, 0, 4)
+               # glColor4ub(5, 171, 231, 96)
+               # glDrawArrays(GL_QUADS, 4, 8)
+               # glColor4ub(5, 171, 231, 128)
+               # glDrawArrays(GL_QUADS, 12, 8)
+               # glDisableClientState(GL_VERTEX_ARRAY)
+
+               polys = profile.getMachineSizePolygons()
+               height = profile.getMachineSettingFloat('machine_height')
+               glBegin(GL_QUADS)
+               for n in xrange(0, len(polys[0])):
+                       if n % 2 == 0:
+                               glColor4ub(5, 171, 231, 96)
+                       else:
+                               glColor4ub(5, 171, 231, 64)
+                       glVertex3f(polys[0][n][0], polys[0][n][1], height)
+                       glVertex3f(polys[0][n][0], polys[0][n][1], 0)
+                       glVertex3f(polys[0][n-1][0], polys[0][n-1][1], 0)
+                       glVertex3f(polys[0][n-1][0], polys[0][n-1][1], height)
+               glEnd()
                glColor4ub(5, 171, 231, 128)
-               glDrawArrays(GL_QUADS, 12, 8)
-               glDisableClientState(GL_VERTEX_ARRAY)
+               glBegin(GL_TRIANGLE_FAN)
+               for p in polys[0][::-1]:
+                       glVertex3f(p[0], p[1], height)
+               glEnd()
 
                #Draw checkerboard
-               sx = self._machineSize[0]
-               sy = self._machineSize[1]
-               for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
-                       for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
-                               x1 = x * 10
-                               x2 = x1 + 10
-                               y1 = y * 10
-                               y2 = y1 + 10
-                               x1 = max(min(x1, sx/2), -sx/2)
-                               y1 = max(min(y1, sy/2), -sy/2)
-                               x2 = max(min(x2, sx/2), -sx/2)
-                               y2 = max(min(y2, sy/2), -sy/2)
-                               #Black or "white"  checker
-                               if (x & 1) == (y & 1):
-                                       glColor4ub(5, 171, 231, 127)
-                               else:
-                                       glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
-                               glBegin(GL_QUADS)
-                               glVertex3f(x1, y1, 0)
-                               glVertex3f(x2, y1, 0)
-                               glVertex3f(x2, y2, 0)
-                               glVertex3f(x1, y2, 0)
-                               glEnd()
+               if self._platformTexture is None:
+                       self._platformTexture = opengl.loadGLTexture('checkerboard.png')
+                       glBindTexture(GL_TEXTURE_2D, self._platformTexture)
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
+               glColor4f(1,1,1,0.5)
+               glBindTexture(GL_TEXTURE_2D, self._platformTexture)
+               glEnable(GL_TEXTURE_2D)
+               glBegin(GL_TRIANGLE_FAN)
+               for p in polys[0]:
+                       glTexCoord2f(p[0]/20, p[1]/20)
+                       glVertex3f(p[0], p[1], 0)
+               glEnd()
+               glDisable(GL_TEXTURE_2D)
+               glColor4ub(127, 127, 127, 200)
+               for poly in polys[1:]:
+                       glBegin(GL_TRIANGLE_FAN)
+                       for p in poly:
+                               glTexCoord2f(p[0]/20, p[1]/20)
+                               glVertex3f(p[0], p[1], 0)
+                       glEnd()
 
-               if machine == 'ultimaker2':
+               if machine == 'ultimaker2x':
 
                        glColor4ub(127, 127, 127, 200)
                        #if UM2, draw bat-area zone for head. THe head can't stop there, because its bat-area.
                        #UpperRight
                        clipWidth = 25
                        clipHeight = 10
-                       posX = sx / 2 - clipWidth
-                       posY = sy / 2 - clipHeight
+                       posX = size[0] / 2 - clipWidth
+                       posY = size[1] / 2 - clipHeight
                        glBegin(GL_QUADS)
                        glVertex3f(posX, posY, 0)
                        glVertex3f(posX+clipWidth, posY, 0)
@@ -1395,8 +1412,8 @@ void main(void)
                        #UpperLeft
                        clipWidth = 25
                        clipHeight = 10
-                       posX = -sx / 2
-                       posY = sy / 2 - clipHeight
+                       posX = -size[0] / 2
+                       posY = size[1] / 2 - clipHeight
                        glBegin(GL_QUADS)
                        glVertex3f(posX, posY, 0)
                        glVertex3f(posX+clipWidth, posY, 0)
@@ -1406,8 +1423,8 @@ void main(void)
                        #LowerRight
                        clipWidth = 25
                        clipHeight = 10
-                       posX = sx / 2 - clipWidth
-                       posY = -sy / 2
+                       posX = size[0] / 2 - clipWidth
+                       posY = -size[1] / 2
                        glBegin(GL_QUADS)
                        glVertex3f(posX, posY, 0)
                        glVertex3f(posX+clipWidth, posY, 0)
@@ -1417,8 +1434,8 @@ void main(void)
                        #LowerLeft
                        clipWidth = 25
                        clipHeight = 10
-                       posX = -sx / 2
-                       posY = -sy / 2
+                       posX = -size[0] / 2
+                       posY = -size[1] / 2
                        glBegin(GL_QUADS)
                        glVertex3f(posX, posY, 0)
                        glVertex3f(posX+clipWidth, posY, 0)
index f50e5721a325a90148eabe42e4b3dce8d5f9ac89..7510a93e493269f2dc5df6fa8a354b632dae9bc5 100644 (file)
@@ -98,9 +98,11 @@ class Scene(object):
                self._gantryHeight = 60
                self._oneAtATime = True
 
-       # Physical (square) machine size.
-       def setMachineSize(self, machineSize):
-               self._machineSize = machineSize
+       # update the physical machine dimensions
+       def updateMachineDimensions(self):
+               self._machineSize = numpy.array([profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')])
+               self._machinePolygons = profile.getMachineSizePolygons()
+               self.setHeadSize(profile.getMachineSettingFloat('extruder_head_size_min_x'), profile.getMachineSettingFloat('extruder_head_size_max_x'), profile.getMachineSettingFloat('extruder_head_size_min_y'), profile.getMachineSettingFloat('extruder_head_size_max_y'), profile.getMachineSettingFloat('extruder_head_size_height'))
 
        # Size offsets are offsets caused by brim, skirt, etc.
        def updateSizeOffsets(self, force=False):
@@ -140,8 +142,8 @@ class Scene(object):
                        obj.applyMatrix(numpy.matrix(matrix, numpy.float64))
                self._findFreePositionFor(obj)
                self._objectList.append(obj)
-               self.pushFree()
                self.updateSizeOffsets(True)
+               self.pushFree()
 
        def remove(self, obj):
                self._objectList.remove(obj)
@@ -217,51 +219,22 @@ class Scene(object):
                        return polygon.polygonCollision(a._boundaryHull + a.getPosition(), b._boundaryHull + b.getPosition())
 
        def checkPlatform(self, obj):
-               p = obj.getPosition()
-               s = obj.getSize()[0:2] / 2 + self._sizeOffsets
-               offsetLeft = 0.0
-               offsetRight = 0.0
-               offsetBack = 0.0
-               offsetFront = 0.0
-               extruderCount = len(obj._meshList)
-               if profile.getProfileSetting('support_dual_extrusion') == 'Second extruder' and profile.getProfileSetting('support') != 'None':
-                       extruderCount = max(extruderCount, 2)
-               for n in xrange(1, extruderCount):
-                       if offsetLeft < self._extruderOffset[n][0]:
-                               offsetLeft = self._extruderOffset[n][0]
-                       if offsetRight > self._extruderOffset[n][0]:
-                               offsetRight = self._extruderOffset[n][0]
-                       if offsetFront < self._extruderOffset[n][1]:
-                               offsetFront = self._extruderOffset[n][1]
-                       if offsetBack > self._extruderOffset[n][1]:
-                               offsetBack = self._extruderOffset[n][1]
-               boundLeft = -self._machineSize[0] / 2 + offsetLeft
-               boundRight = self._machineSize[0] / 2 + offsetRight
-               boundFront = -self._machineSize[1] / 2 + offsetFront
-               boundBack = self._machineSize[1] / 2 + offsetBack
-               if p[0] - s[0] < boundLeft:
-                       return False
-               if p[0] + s[0] > boundRight:
-                       return False
-               if p[1] - s[1] < boundFront:
-                       return False
-               if p[1] + s[1] > boundBack:
+               area = obj._printAreaHull + obj.getPosition()
+               if not polygon.fullInside(area, self._machinePolygons[0]):
                        return False
-
-               #Do clip Check for UM2.
-               machine = profile.getMachineSetting('machine_type')
-               if machine == "ultimaker2":
-                       #lowerRight clip check
-                       if p[0] - s[0] < boundLeft + 25 and p[1] - s[1] < boundFront + 10:
-                               return False
-                       #UpperRight
-                       if p[0] - s[0] < boundLeft + 25 and p[1] + s[1] > boundBack - 10:
-                               return False
-                       #LowerLeft
-                       if p[0] + s[0] > boundRight - 25 and p[1] - s[1] < boundFront + 10:
-                               return False
-                       #UpperLeft
-                       if p[0] + s[0] > boundRight - 25 and p[1] + s[1] > boundBack - 10:
+               # aMin = numpy.min(area, 0)
+               # aMax = numpy.max(area, 0)
+               # if aMin[0] < -self._machineSize[0] / 2:
+               #       return False
+               # if aMax[0] > self._machineSize[0] / 2:
+               #       return False
+               # if aMin[1] < -self._machineSize[1] / 2:
+               #       return False
+               # if aMax[1] > self._machineSize[1] / 2:
+               #       return False
+               #Check the "no go zones"
+               for poly in self._machinePolygons[1:]:
+                       if polygon.polygonCollision(poly, area):
                                return False
                return True
 
index a6592fec5a056c11c38710667b8f28e77051ed35..9b7a987bff89cbf5d2401202a676cf3131a46ab2 100644 (file)
@@ -120,6 +120,34 @@ def polygonCollisionPushVector(polyA, polyB):
                        retSize = size
        return ret
 
+#Check if polyA is fully inside of polyB.
+def fullInside(polyA, polyB):
+       for n in xrange(0, len(polyA)):
+               p0 = polyA[n-1]
+               p1 = polyA[n]
+               normal = (p1 - p0)[::-1]
+               normal[1] = -normal[1]
+               normal /= numpy.linalg.norm(normal)
+               aMin, aMax = projectPoly(polyA, normal)
+               bMin, bMax = projectPoly(polyB, normal)
+               if aMax > bMax:
+                       return False
+               if aMin < bMin:
+                       return False
+       for n in xrange(0, len(polyB)):
+               p0 = polyB[n-1]
+               p1 = polyB[n]
+               normal = (p1 - p0)[::-1]
+               normal[1] = -normal[1]
+               normal /= numpy.linalg.norm(normal)
+               aMin, aMax = projectPoly(polyA, normal)
+               bMin, bMax = projectPoly(polyB, normal)
+               if aMax > bMax:
+                       return False
+               if aMin < bMin:
+                       return False
+       return True
+
 def isLeft(a, b, c):
        return ((b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0])) > 0
 
index 65128f0d078ae586a481f08efc887516a7a7f0f1..a2f0255a17a5ed5818f67907b4a6bef1aa3391ed 100644 (file)
@@ -4,6 +4,7 @@ __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AG
 
 import os, traceback, math, re, zlib, base64, time, sys, platform, glob, string, stat, types
 import cPickle as pickle
+import numpy
 if sys.version_info[0] < 3:
        import ConfigParser
 else:
@@ -870,6 +871,30 @@ def getMachineCenterCoords():
                return [0, 0]
        return [getMachineSettingFloat('machine_width') / 2, getMachineSettingFloat('machine_depth') / 2]
 
+#Returns a list of convex polygons, first polygon is the allowed area of the machine,
+# the rest of the polygons are the dis-allowed areas of the machine.
+def getMachineSizePolygons():
+       size = numpy.array([getMachineSettingFloat('machine_width'), getMachineSettingFloat('machine_depth'), getMachineSettingFloat('machine_height')], numpy.float32)
+       ret = []
+       ret.append(numpy.array([[-size[0]/2,-size[1]/2],[ size[0]/2,-size[1]/2],[ size[0]/2, size[1]/2], [-size[0]/2, size[1]/2]], numpy.float32))
+
+       # Circle platform for delta printers...
+       # circle = []
+       # steps = 16
+       # for n in xrange(0, steps):
+       #       circle.append([math.cos(float(n)/steps*2*math.pi) * size[0]/2, math.sin(float(n)/steps*2*math.pi) * size[0]/2])
+       # ret.append(numpy.array(circle, numpy.float32))
+
+       if getMachineSetting('machine_type') == 'ultimaker2':
+               #UM2 no-go zones
+               w = 25
+               h = 10
+               ret.append(numpy.array([[-size[0]/2,-size[1]/2],[-size[0]/2+w+2,-size[1]/2], [-size[0]/2+w,-size[1]/2+h], [-size[0]/2,-size[1]/2+h]], numpy.float32))
+               ret.append(numpy.array([[ size[0]/2-w-2,-size[1]/2],[ size[0]/2,-size[1]/2], [ size[0]/2,-size[1]/2+h],[ size[0]/2-w,-size[1]/2+h]], numpy.float32))
+               ret.append(numpy.array([[-size[0]/2+w+2, size[1]/2],[-size[0]/2, size[1]/2], [-size[0]/2, size[1]/2-h],[-size[0]/2+w, size[1]/2-h]], numpy.float32))
+               ret.append(numpy.array([[ size[0]/2, size[1]/2],[ size[0]/2-w-2, size[1]/2], [ size[0]/2-w, size[1]/2-h],[ size[0]/2, size[1]/2-h]], numpy.float32))
+       return ret
+
 #########################################################
 ## Alteration file functions
 #########################################################