Increase performance and decrease memory usage by using numpy library for 3D models. Saves more then 50% memory, and is about 30% faster when loading models. I think more performance can be gained with this library.

This commit is contained in:
daid 2012-07-26 16:30:43 +02:00
parent e698fb067d
commit 8069d0633f
6 changed files with 164 additions and 179 deletions

View File

@ -180,44 +180,44 @@ def ResetMatrixRotationAndScale():
def DrawBox(vMin, vMax):
glBegin(GL_LINE_LOOP)
glVertex3f(vMin.x, vMin.y, vMin.z)
glVertex3f(vMax.x, vMin.y, vMin.z)
glVertex3f(vMax.x, vMax.y, vMin.z)
glVertex3f(vMin.x, vMax.y, vMin.z)
glVertex3f(vMin[0], vMin[1], vMin[2])
glVertex3f(vMax[0], vMin[1], vMin[2])
glVertex3f(vMax[0], vMax[1], vMin[2])
glVertex3f(vMin[0], vMax[1], vMin[2])
glEnd()
glBegin(GL_LINE_LOOP)
glVertex3f(vMin.x, vMin.y, vMax.z)
glVertex3f(vMax.x, vMin.y, vMax.z)
glVertex3f(vMax.x, vMax.y, vMax.z)
glVertex3f(vMin.x, vMax.y, vMax.z)
glVertex3f(vMin[0], vMin[1], vMax[2])
glVertex3f(vMax[0], vMin[1], vMax[2])
glVertex3f(vMax[0], vMax[1], vMax[2])
glVertex3f(vMin[0], vMax[1], vMax[2])
glEnd()
glBegin(GL_LINES)
glVertex3f(vMin.x, vMin.y, vMin.z)
glVertex3f(vMin.x, vMin.y, vMax.z)
glVertex3f(vMax.x, vMin.y, vMin.z)
glVertex3f(vMax.x, vMin.y, vMax.z)
glVertex3f(vMax.x, vMax.y, vMin.z)
glVertex3f(vMax.x, vMax.y, vMax.z)
glVertex3f(vMin.x, vMax.y, vMin.z)
glVertex3f(vMin.x, vMax.y, vMax.z)
glVertex3f(vMin[0], vMin[1], vMin[2])
glVertex3f(vMin[0], vMin[1], vMax[2])
glVertex3f(vMax[0], vMin[1], vMin[2])
glVertex3f(vMax[0], vMin[1], vMax[2])
glVertex3f(vMax[0], vMax[1], vMin[2])
glVertex3f(vMax[0], vMax[1], vMax[2])
glVertex3f(vMin[0], vMax[1], vMin[2])
glVertex3f(vMin[0], vMax[1], vMax[2])
glEnd()
def DrawSTL(mesh):
glEnable(GL_CULL_FACE)
for face in mesh.faces:
for i in xrange(0, mesh.vertexCount, 3):
glBegin(GL_TRIANGLES)
v1 = face.v[0]
v2 = face.v[1]
v3 = face.v[2]
glNormal3f(face.normal.x, face.normal.y, face.normal.z)
glVertex3f(v1.x, v1.y, v1.z)
glVertex3f(v2.x, v2.y, v2.z)
glVertex3f(v3.x, v3.y, v3.z)
glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z)
glVertex3f(v1.x, v1.y, v1.z)
glVertex3f(v3.x, v3.y, v3.z)
glVertex3f(v2.x, v2.y, v2.z)
v1 = mesh.vertexes[i]
v2 = mesh.vertexes[i+1]
v3 = mesh.vertexes[i+2]
glNormal3f(mesh.normal[i/3][0], mesh.normal[i/3][1], mesh.normal[i/3][2])
glVertex3f(v1[0], v1[1], v1[2])
glVertex3f(v2[0], v2[1], v2[2])
glVertex3f(v3[0], v3[1], v3[2])
glNormal3f(-mesh.normal[i/3][0], -mesh.normal[i/3][1], -mesh.normal[i/3][2])
glVertex3f(v1[0], v1[1], v1[2])
glVertex3f(v2[0], v2[1], v2[2])
glVertex3f(v3[0], v3[1], v3[2])
glEnd()
def DrawGCodeLayer(layer):

View File

@ -1,6 +1,7 @@
from __future__ import division
import sys, math, threading, re, time, os
import numpy
from wx import glcanvas
import wx
@ -170,11 +171,11 @@ class previewPanel(wx.Panel):
return
vMin = self.objectsMinV
vMax = self.objectsMaxV
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
scaleY2 = (self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
scaleZ = self.machineSize.z / (vMax.z - vMin.z)
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax[0] - vMin[0]) / 2)
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
scaleX2 = (self.machineCenter.x) / ((vMax[0] - vMin[1]) / 2)
scaleY2 = (self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
scaleZ = self.machineSize.z / (vMax[2] - vMin[2])
scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
self.scale.SetValue(str(scale))
profile.putProfileSetting('model_scale', self.scale.GetValue())
@ -356,8 +357,8 @@ class previewPanel(wx.Panel):
continue
obj.mesh.getMinimumZ()
minV = minV.min(obj.mesh.getMinimum())
maxV = maxV.max(obj.mesh.getMaximum())
minV = numpy.minimum(minV, obj.mesh.getMinimum())
maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
self.objectsMaxV = maxV
self.objectsMinV = minV
@ -365,10 +366,11 @@ class previewPanel(wx.Panel):
if obj.mesh == None:
continue
for v in obj.mesh.vertexes:
v.z -= minV.z
v.x -= minV.x + (maxV.x - minV.x) / 2
v.y -= minV.y + (maxV.y - minV.y) / 2
obj.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2]])
#for v in obj.mesh.vertexes:
# v[2] -= minV[2]
# v[0] -= minV[0] + (maxV[0] - minV[0]) / 2
# v[1] -= minV[1] + (maxV[1] - minV[1]) / 2
obj.mesh.getMinimumZ()
obj.dirty = True
self.glCanvas.Refresh()
@ -461,7 +463,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z)
else:
if self.parent.objectsMaxV != None:
glTranslate(0,0,-self.parent.objectsMaxV.z * profile.getProfileSettingFloat('model_scale') / 2)
glTranslate(0,0,-self.parent.objectsMaxV[2] * profile.getProfileSettingFloat('model_scale') / 2)
else:
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
glTranslate(self.offsetX, self.offsetY, 0.0)
@ -610,11 +612,11 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
modelScale = profile.getProfileSettingFloat('model_scale')
modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale
glPushMatrix()
glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0)
glTranslate(-(modelSize[0]+10)*(multiX-1)/2,-(modelSize[1]+10)*(multiY-1)/2, 0)
for mx in xrange(0, multiX):
for my in xrange(0, multiY):
glPushMatrix()
glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0)
glTranslate((modelSize[0]+10)*mx,(modelSize[1]+10)*my, 0)
glScalef(modelScale, modelScale, modelScale)
glCallList(obj.displayList)
glPopMatrix()

View File

@ -3,9 +3,9 @@ import __init__
import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re
import ConfigParser
import numpy
from wx import glcanvas
import wx
try:
import OpenGL
OpenGL.ERROR_CHECKING = False
@ -55,18 +55,15 @@ class ProjectObject(stl.stlModel):
self.modelDisplayList = None
self.modelDirty = False
self.origonalVertexes = list(self.vertexes)
for i in xrange(0, len(self.origonalVertexes)):
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
self.getMinimumZ()
self.centerX = -self.getMinimum().x + 5
self.centerY = -self.getMinimum().y + 5
self.centerX = -self.getMinimum()[0] + 5
self.centerY = -self.getMinimum()[1] + 5
self.updateModelTransform()
self.centerX = -self.getMinimum().x + 5
self.centerY = -self.getMinimum().y + 5
self.centerX = -self.getMinimum()[0] + 5
self.centerY = -self.getMinimum()[1] + 5
def isSameExceptForPosition(self, other):
if self.filename != other.filename:
@ -96,10 +93,7 @@ class ProjectObject(stl.stlModel):
minZ = self.getMinimumZ()
minV = self.getMinimum()
maxV = self.getMaximum()
for v in self.vertexes:
v.z -= minZ
v.x -= minV.x + (maxV.x - minV.x) / 2
v.y -= minV.y + (maxV.y - minV.y) / 2
self.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])
minZ = self.getMinimumZ()
self.modelDirty = True
@ -125,14 +119,14 @@ class ProjectObject(stl.stlModel):
return p
def clampXY(self):
if self.centerX < -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x:
self.centerX = -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x
if self.centerY < -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y:
self.centerY = -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y
if self.centerX > self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale:
self.centerX = self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale
if self.centerY > self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale:
self.centerY = self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale
if self.centerX < -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]:
self.centerX = -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]
if self.centerY < -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]:
self.centerY = -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]
if self.centerX > self.parent.machineSize[0] + self.parent.extruderOffset[self.extruder][0] - self.getMaximum()[0] * self.scale:
self.centerX = self.parent.machineSize[0] + self.parent.extruderOffset[self.extruder][0] - self.getMaximum()[0] * self.scale
if self.centerY > self.parent.machineSize[1] + self.parent.extruderOffset[self.extruder][1] - self.getMaximum()[1] * self.scale:
self.centerY = self.parent.machineSize[1] + self.parent.extruderOffset[self.extruder][1] - self.getMaximum()[1] * self.scale
class projectPlanner(wx.Frame):
"Main user interface window"
@ -151,15 +145,15 @@ class projectPlanner(wx.Frame):
self.selection = None
self.printMode = 0
self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height'))
self.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0)
self.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0)
self.machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
self.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
self.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
self.extruderOffset = [
util3d.Vector3(0,0,0),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0)]
numpy.array([0,0,0]),
numpy.array([profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0]),
numpy.array([profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0]),
numpy.array([profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0])]
self.toolbar = toolbarUtil.Toolbar(self.panel)
@ -392,7 +386,7 @@ class projectPlanner(wx.Frame):
def OnTopClick(self):
self.preview.view3D = False
self.preview.zoom = self.machineSize.x / 2 + 10
self.preview.zoom = self.machineSize[0] / 2 + 10
self.preview.offsetX = 0
self.preview.offsetY = 0
self.preview.Refresh()
@ -499,9 +493,9 @@ class projectPlanner(wx.Frame):
self.listbox.SetSelection(-1)
def OnAutoPlace(self, e):
bestAllowedSize = int(self.machineSize.y)
bestAllowedSize = int(self.machineSize[1])
bestArea = self._doAutoPlace(bestAllowedSize)
for i in xrange(10, int(self.machineSize.y), 10):
for i in xrange(10, int(self.machineSize[1]), 10):
area = self._doAutoPlace(i)
if area < bestArea:
bestAllowedSize = i
@ -516,18 +510,18 @@ class projectPlanner(wx.Frame):
extraSizeMax = self.headSizeMax
if profile.getProfileSettingFloat('skirt_line_count') > 0:
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0)
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0)
extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
if profile.getProfileSetting('support') != 'None':
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0)
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0)
extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
if self.printMode == 1:
extraSizeMin = util3d.Vector3(6.0, 6.0, 0)
extraSizeMax = util3d.Vector3(6.0, 6.0, 0)
extraSizeMin = numpy.array([6.0, 6.0, 0])
extraSizeMax = numpy.array([6.0, 6.0, 0])
if extraSizeMin.x > extraSizeMax.x:
posX = self.machineSize.x
if extraSizeMin[0] > extraSizeMax[0]:
posX = self.machineSize[0]
dirX = -1
else:
posX = 0
@ -535,35 +529,35 @@ class projectPlanner(wx.Frame):
posY = 0
dirY = 1
minX = self.machineSize.x
minY = self.machineSize.y
minX = self.machineSize[0]
minY = self.machineSize[1]
maxX = 0
maxY = 0
for item in self.list:
item.centerX = posX + item.getMaximum().x * item.scale * dirX
item.centerY = posY + item.getMaximum().y * item.scale * dirY
if item.centerY + item.getSize().y >= allowedSizeY:
item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
if item.centerY + item.getSize()[1] >= allowedSizeY:
if dirX < 0:
posX = minX - extraSizeMax.x - 1
posX = minX - extraSizeMax[0] - 1
else:
posX = maxX + extraSizeMin.x + 1
posX = maxX + extraSizeMin[0] + 1
posY = 0
item.centerX = posX + item.getMaximum().x * item.scale * dirX
item.centerY = posY + item.getMaximum().y * item.scale * dirY
posY += item.getSize().y * item.scale * dirY + extraSizeMin.y + 1
minX = min(minX, item.centerX - item.getSize().x * item.scale / 2)
minY = min(minY, item.centerY - item.getSize().y * item.scale / 2)
maxX = max(maxX, item.centerX + item.getSize().x * item.scale / 2)
maxY = max(maxY, item.centerY + item.getSize().y * item.scale / 2)
item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
posY += item.getSize()[1] * item.scale * dirY + extraSizeMin[1] + 1
minX = min(minX, item.centerX - item.getSize()[0] * item.scale / 2)
minY = min(minY, item.centerY - item.getSize()[1] * item.scale / 2)
maxX = max(maxX, item.centerX + item.getSize()[0] * item.scale / 2)
maxY = max(maxY, item.centerY + item.getSize()[1] * item.scale / 2)
for item in self.list:
if dirX < 0:
item.centerX -= minX / 2
else:
item.centerX += (self.machineSize.x - maxX) / 2
item.centerY += (self.machineSize.y - maxY) / 2
item.centerX += (self.machineSize[0] - maxX) / 2
item.centerY += (self.machineSize[1] - maxY) / 2
if minX < 0 or maxX > self.machineSize.x:
if minX < 0 or maxX > self.machineSize[0]:
return ((maxX - minX) + (maxY - minY)) * 100
return (maxX - minX) + (maxY - minY)
@ -590,8 +584,8 @@ class projectPlanner(wx.Frame):
for item in self.list:
if item.profile != None and os.path.isfile(item.profile):
profile.loadGlobalProfile(item.profile)
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder].x)
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder].y)
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder][0])
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder][1])
put('model_scale', item.scale)
put('flip_x', item.flipX)
put('flip_y', item.flipY)
@ -607,7 +601,7 @@ class projectPlanner(wx.Frame):
action.temperature = profile.getProfileSettingFloat('print_temperature')
action.extruder = item.extruder
action.filename = item.filename
clearZ = max(clearZ, item.getMaximum().z * item.scale + 5.0)
clearZ = max(clearZ, item.getMaximum()[2] * item.scale + 5.0)
action.clearZ = clearZ
action.leaveResultForNextSlice = False
action.usePreviousSlice = False
@ -698,7 +692,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
self.yaw = 30
self.pitch = 60
self.zoom = self.parent.machineSize.x / 2 + 10
self.zoom = self.parent.machineSize[0] / 2 + 10
self.offsetX = 0
self.offsetY = 0
self.view3D = False
@ -760,32 +754,30 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glTranslate(0,0,-self.zoom)
glRotate(-self.pitch, 1,0,0)
glRotate(self.yaw, 0,0,1)
if False: #self.parent.triangleMesh != None:
glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)
else:
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
glTranslate(self.offsetX, self.offsetY, 0.0)
glTranslate(-self.parent.machineSize.x/2, -self.parent.machineSize.y/2, 0)
glTranslate(-self.parent.machineSize[0]/2, -self.parent.machineSize[1]/2, 0)
self.OnDraw()
self.SwapBuffers()
def OnDraw(self):
machineSize = self.parent.machineSize
opengl.DrawMachine(machineSize)
opengl.DrawMachine(util3d.Vector3(machineSize[0], machineSize[1], machineSize[2]))
extraSizeMin = self.parent.headSizeMin
extraSizeMax = self.parent.headSizeMax
if profile.getProfileSettingFloat('skirt_line_count') > 0:
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0)
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0)
extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
if profile.getProfileSetting('support') != 'None':
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0)
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0)
extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
if self.parent.printMode == 1:
extraSizeMin = util3d.Vector3(6.0, 6.0, 0)
extraSizeMax = util3d.Vector3(6.0, 6.0, 0)
extraSizeMin = numpy.array([6.0, 6.0, 0])
extraSizeMax = numpy.array([6.0, 6.0, 0])
for item in self.parent.list:
item.validPlacement = True
@ -793,13 +785,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
for idx1 in xrange(0, len(self.parent.list)):
item = self.parent.list[idx1]
iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - extraSizeMin - self.parent.extruderOffset[item.extruder]
iMax1 = item.getMaximum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) + extraSizeMax - self.parent.extruderOffset[item.extruder]
iMin1 = (item.getMinimum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) - extraSizeMin - self.parent.extruderOffset[item.extruder]
iMax1 = (item.getMaximum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) + extraSizeMax - self.parent.extruderOffset[item.extruder]
for idx2 in xrange(0, idx1):
item2 = self.parent.list[idx2]
iMin2 = item2.getMinimum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)
iMax2 = item2.getMaximum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)
if item != item2 and iMax1.x >= iMin2.x and iMin1.x <= iMax2.x and iMax1.y >= iMin2.y and iMin1.y <= iMax2.y:
iMin2 = (item2.getMinimum() * item2.scale) + numpy.array([item2.centerX, item2.centerY, 0])
iMax2 = (item2.getMaximum() * item2.scale) + numpy.array([item2.centerX, item2.centerY, 0])
if item != item2 and iMax1[0] >= iMin2[0] and iMin1[0] <= iMax2[0] and iMax1[1] >= iMin2[1] and iMin1[1] <= iMax2[1]:
item.validPlacement = False
item2.gotHit = True
@ -959,8 +951,8 @@ class ProjectSliceProgressWindow(wx.Frame):
line = p.stdout.readline()
self.returnCode = p.wait()
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x)
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y)
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder][0])
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder][1])
put('clear_z', action.clearZ)
put('extruder', action.extruder)
put('print_temperature', action.temperature)
@ -1089,8 +1081,8 @@ class preferencesDialog(configBase.configWindowBase):
self.Fit()
def OnClose(self, e):
self.parent.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0)
self.parent.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0)
self.parent.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
self.parent.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
self.parent.Refresh()
self.MakeModal(False)

View File

@ -2,41 +2,36 @@ import sys, math, re, os, struct, time
import util3d
class meshFace(object):
def __init__(self, v0, v1, v2):
self.v = [v0, v1, v2]
import numpy
class mesh(object):
def __init__(self):
self.faces = []
self.vertexes = []
self.vertexes = None
self.origonalVertexes = None
self.vertexCount = 0
def addFace(self, v0, v1, v2):
self.vertexes.append(v0)
self.vertexes.append(v1)
self.vertexes.append(v2)
self.faces.append(meshFace(v0, v1, v2))
def addVertex(self, x, y, z):
n = self.vertexCount
self.origonalVertexes[n][0] = x
self.origonalVertexes[n][1] = y
self.origonalVertexes[n][2] = z
self.vertexCount += 1
def _prepareVertexCount(self, vertexNumber):
#Set the amount of faces before loading data in them. This way we can create the numpy arrays before we fill them.
self.origonalVertexes = numpy.zeros((vertexNumber, 3), float)
self.normal = numpy.zeros((vertexNumber / 3, 3))
self.vertexCount = 0
def _postProcessAfterLoad(self):
self.origonalVertexes = list(self.vertexes)
for i in xrange(0, len(self.origonalVertexes)):
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
self.vertexes = self.origonalVertexes.copy()
self.getMinimumZ()
def getMinimumZ(self):
minv = self.vertexes[0].copy()
maxv = self.vertexes[0].copy()
for v in self.vertexes:
minv.x = min(minv.x, v.x)
minv.y = min(minv.y, v.y)
minv.z = min(minv.z, v.z)
maxv.x = max(maxv.x, v.x)
maxv.y = max(maxv.y, v.y)
maxv.z = max(maxv.z, v.z)
self.min = minv
self.max = maxv
self.size = maxv - minv
return self.min.z
self.min = self.vertexes.min(0)
self.max = self.vertexes.max(0)
self.size = self.max - self.min
return self.min[2]
def getMaximum(self):
return self.max
@ -62,23 +57,23 @@ class mesh(object):
mat11 = math.cos(rotate) * scaleY
for i in xrange(0, len(self.origonalVertexes)):
x = self.origonalVertexes[i].x
y = self.origonalVertexes[i].y
z = self.origonalVertexes[i].z
x = self.origonalVertexes[i][0]
y = self.origonalVertexes[i][1]
z = self.origonalVertexes[i][2]
if swapXZ:
x, z = z, x
if swapYZ:
y, z = z, y
self.vertexes[i].x = x * mat00 + y * mat01
self.vertexes[i].y = x * mat10 + y * mat11
self.vertexes[i].z = z * scaleZ
self.vertexes[i][0] = x * mat00 + y * mat01
self.vertexes[i][1] = x * mat10 + y * mat11
self.vertexes[i][2] = z * scaleZ
for face in self.faces:
v1 = face.v[0]
v2 = face.v[1]
v3 = face.v[2]
face.normal = (v2 - v1).cross(v3 - v1)
face.normal.normalize()
for i in xrange(0, len(self.origonalVertexes), 3):
v1 = self.vertexes[i]
v2 = self.vertexes[i+1]
v3 = self.vertexes[i+2]
self.normal[i/3] = numpy.cross((v2 - v1), (v3 - v1))
self.normal[i/3] /= (self.normal[i/3] * self.normal[i/3]).sum()
self.getMinimumZ()

View File

@ -1,6 +1,5 @@
import sys, math, re, os, struct, time
import util3d
import mesh
class stlModel(mesh.mesh):
@ -11,7 +10,7 @@ class stlModel(mesh.mesh):
f = open(filename, "rb")
if f.read(5).lower() == "solid":
self._loadAscii(f)
if not self.faces:
if self.vertexCount < 3:
f.seek(5, os.SEEK_SET)
self._loadBinary(f)
else:
@ -22,31 +21,28 @@ class stlModel(mesh.mesh):
return self
def _loadAscii(self, f):
cnt = 0
for line in f:
if 'vertex' in line:
cnt += 1
self._prepareVertexCount(int(cnt))
f.seek(5, os.SEEK_SET)
cnt = 0
for line in f:
if 'vertex' in line:
data = line.split()
if cnt == 0:
v0 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
cnt = 1
elif cnt == 1:
v1 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
cnt = 2
elif cnt == 2:
v2 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
self.addFace(v0, v1, v2)
cnt = 0
self.addVertex(float(data[1]), float(data[2]), float(data[3]))
def _loadBinary(self, f):
#Skip the header
f.read(80-5)
faceCount = struct.unpack('<I', f.read(4))[0]
self._prepareVertexCount(faceCount * 3)
for idx in xrange(0, faceCount):
data = struct.unpack("<ffffffffffffH", f.read(50))
v0 = util3d.Vector3(data[3], data[4], data[5])
v1 = util3d.Vector3(data[6], data[7], data[8])
v2 = util3d.Vector3(data[9], data[10], data[11])
self.addFace(v0, v1, v2)
self.addVertex(data[3], data[4], data[5])
self.addVertex(data[6], data[7], data[8])
self.addVertex(data[9], data[10], data[11])
def saveAsSTL(mesh, filename):
f = open(filename, 'wb')
@ -70,8 +66,8 @@ def saveAsSTL(mesh, filename):
if __name__ == '__main__':
for filename in sys.argv[1:]:
m = stlModel().load(filename)
print("Loaded %d faces" % (len(m.faces)))
parts = m.splitToParts()
for p in parts:
saveAsSTL(p, "export_%i.stl" % parts.index(p))
print("Loaded %d faces" % (m.vertexCount / 3))
# parts = m.splitToParts()
# for p in parts:
# saveAsSTL(p, "export_%i.stl" % parts.index(p))

View File

@ -13,7 +13,7 @@ class Vector3(object):
return Vector3(self.x, self.y, self.z)
def __repr__(self):
return '[%s, %s, %s]' % ( self.x, self.y, self.z )
return 'V[%s, %s, %s]' % ( self.x, self.y, self.z )
def __add__(self, v):
return Vector3( self.x + v.x, self.y + v.y, self.z + v.z )