mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-18 14:25:56 +08:00
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:
parent
e698fb067d
commit
8069d0633f
@ -180,44 +180,44 @@ def ResetMatrixRotationAndScale():
|
|||||||
|
|
||||||
def DrawBox(vMin, vMax):
|
def DrawBox(vMin, vMax):
|
||||||
glBegin(GL_LINE_LOOP)
|
glBegin(GL_LINE_LOOP)
|
||||||
glVertex3f(vMin.x, vMin.y, vMin.z)
|
glVertex3f(vMin[0], vMin[1], vMin[2])
|
||||||
glVertex3f(vMax.x, vMin.y, vMin.z)
|
glVertex3f(vMax[0], vMin[1], vMin[2])
|
||||||
glVertex3f(vMax.x, vMax.y, vMin.z)
|
glVertex3f(vMax[0], vMax[1], vMin[2])
|
||||||
glVertex3f(vMin.x, vMax.y, vMin.z)
|
glVertex3f(vMin[0], vMax[1], vMin[2])
|
||||||
glEnd()
|
glEnd()
|
||||||
|
|
||||||
glBegin(GL_LINE_LOOP)
|
glBegin(GL_LINE_LOOP)
|
||||||
glVertex3f(vMin.x, vMin.y, vMax.z)
|
glVertex3f(vMin[0], vMin[1], vMax[2])
|
||||||
glVertex3f(vMax.x, vMin.y, vMax.z)
|
glVertex3f(vMax[0], vMin[1], vMax[2])
|
||||||
glVertex3f(vMax.x, vMax.y, vMax.z)
|
glVertex3f(vMax[0], vMax[1], vMax[2])
|
||||||
glVertex3f(vMin.x, vMax.y, vMax.z)
|
glVertex3f(vMin[0], vMax[1], vMax[2])
|
||||||
glEnd()
|
glEnd()
|
||||||
glBegin(GL_LINES)
|
glBegin(GL_LINES)
|
||||||
glVertex3f(vMin.x, vMin.y, vMin.z)
|
glVertex3f(vMin[0], vMin[1], vMin[2])
|
||||||
glVertex3f(vMin.x, vMin.y, vMax.z)
|
glVertex3f(vMin[0], vMin[1], vMax[2])
|
||||||
glVertex3f(vMax.x, vMin.y, vMin.z)
|
glVertex3f(vMax[0], vMin[1], vMin[2])
|
||||||
glVertex3f(vMax.x, vMin.y, vMax.z)
|
glVertex3f(vMax[0], vMin[1], vMax[2])
|
||||||
glVertex3f(vMax.x, vMax.y, vMin.z)
|
glVertex3f(vMax[0], vMax[1], vMin[2])
|
||||||
glVertex3f(vMax.x, vMax.y, vMax.z)
|
glVertex3f(vMax[0], vMax[1], vMax[2])
|
||||||
glVertex3f(vMin.x, vMax.y, vMin.z)
|
glVertex3f(vMin[0], vMax[1], vMin[2])
|
||||||
glVertex3f(vMin.x, vMax.y, vMax.z)
|
glVertex3f(vMin[0], vMax[1], vMax[2])
|
||||||
glEnd()
|
glEnd()
|
||||||
|
|
||||||
def DrawSTL(mesh):
|
def DrawSTL(mesh):
|
||||||
glEnable(GL_CULL_FACE)
|
glEnable(GL_CULL_FACE)
|
||||||
for face in mesh.faces:
|
for i in xrange(0, mesh.vertexCount, 3):
|
||||||
glBegin(GL_TRIANGLES)
|
glBegin(GL_TRIANGLES)
|
||||||
v1 = face.v[0]
|
v1 = mesh.vertexes[i]
|
||||||
v2 = face.v[1]
|
v2 = mesh.vertexes[i+1]
|
||||||
v3 = face.v[2]
|
v3 = mesh.vertexes[i+2]
|
||||||
glNormal3f(face.normal.x, face.normal.y, face.normal.z)
|
glNormal3f(mesh.normal[i/3][0], mesh.normal[i/3][1], mesh.normal[i/3][2])
|
||||||
glVertex3f(v1.x, v1.y, v1.z)
|
glVertex3f(v1[0], v1[1], v1[2])
|
||||||
glVertex3f(v2.x, v2.y, v2.z)
|
glVertex3f(v2[0], v2[1], v2[2])
|
||||||
glVertex3f(v3.x, v3.y, v3.z)
|
glVertex3f(v3[0], v3[1], v3[2])
|
||||||
glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z)
|
glNormal3f(-mesh.normal[i/3][0], -mesh.normal[i/3][1], -mesh.normal[i/3][2])
|
||||||
glVertex3f(v1.x, v1.y, v1.z)
|
glVertex3f(v1[0], v1[1], v1[2])
|
||||||
glVertex3f(v3.x, v3.y, v3.z)
|
glVertex3f(v2[0], v2[1], v2[2])
|
||||||
glVertex3f(v2.x, v2.y, v2.z)
|
glVertex3f(v3[0], v3[1], v3[2])
|
||||||
glEnd()
|
glEnd()
|
||||||
|
|
||||||
def DrawGCodeLayer(layer):
|
def DrawGCodeLayer(layer):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import sys, math, threading, re, time, os
|
import sys, math, threading, re, time, os
|
||||||
|
import numpy
|
||||||
|
|
||||||
from wx import glcanvas
|
from wx import glcanvas
|
||||||
import wx
|
import wx
|
||||||
@ -170,11 +171,11 @@ class previewPanel(wx.Panel):
|
|||||||
return
|
return
|
||||||
vMin = self.objectsMinV
|
vMin = self.objectsMinV
|
||||||
vMax = self.objectsMaxV
|
vMax = self.objectsMaxV
|
||||||
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax[0] - vMin[0]) / 2)
|
||||||
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
|
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
|
||||||
scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
scaleX2 = (self.machineCenter.x) / ((vMax[0] - vMin[1]) / 2)
|
||||||
scaleY2 = (self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
|
scaleY2 = (self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
|
||||||
scaleZ = self.machineSize.z / (vMax.z - vMin.z)
|
scaleZ = self.machineSize.z / (vMax[2] - vMin[2])
|
||||||
scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
|
scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
|
||||||
self.scale.SetValue(str(scale))
|
self.scale.SetValue(str(scale))
|
||||||
profile.putProfileSetting('model_scale', self.scale.GetValue())
|
profile.putProfileSetting('model_scale', self.scale.GetValue())
|
||||||
@ -356,8 +357,8 @@ class previewPanel(wx.Panel):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
obj.mesh.getMinimumZ()
|
obj.mesh.getMinimumZ()
|
||||||
minV = minV.min(obj.mesh.getMinimum())
|
minV = numpy.minimum(minV, obj.mesh.getMinimum())
|
||||||
maxV = maxV.max(obj.mesh.getMaximum())
|
maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
|
||||||
|
|
||||||
self.objectsMaxV = maxV
|
self.objectsMaxV = maxV
|
||||||
self.objectsMinV = minV
|
self.objectsMinV = minV
|
||||||
@ -365,10 +366,11 @@ class previewPanel(wx.Panel):
|
|||||||
if obj.mesh == None:
|
if obj.mesh == None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for v in obj.mesh.vertexes:
|
obj.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2]])
|
||||||
v.z -= minV.z
|
#for v in obj.mesh.vertexes:
|
||||||
v.x -= minV.x + (maxV.x - minV.x) / 2
|
# v[2] -= minV[2]
|
||||||
v.y -= minV.y + (maxV.y - minV.y) / 2
|
# v[0] -= minV[0] + (maxV[0] - minV[0]) / 2
|
||||||
|
# v[1] -= minV[1] + (maxV[1] - minV[1]) / 2
|
||||||
obj.mesh.getMinimumZ()
|
obj.mesh.getMinimumZ()
|
||||||
obj.dirty = True
|
obj.dirty = True
|
||||||
self.glCanvas.Refresh()
|
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)
|
glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z)
|
||||||
else:
|
else:
|
||||||
if self.parent.objectsMaxV != None:
|
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:
|
else:
|
||||||
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
||||||
glTranslate(self.offsetX, self.offsetY, 0.0)
|
glTranslate(self.offsetX, self.offsetY, 0.0)
|
||||||
@ -610,11 +612,11 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
|||||||
modelScale = profile.getProfileSettingFloat('model_scale')
|
modelScale = profile.getProfileSettingFloat('model_scale')
|
||||||
modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale
|
modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale
|
||||||
glPushMatrix()
|
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 mx in xrange(0, multiX):
|
||||||
for my in xrange(0, multiY):
|
for my in xrange(0, multiY):
|
||||||
glPushMatrix()
|
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)
|
glScalef(modelScale, modelScale, modelScale)
|
||||||
glCallList(obj.displayList)
|
glCallList(obj.displayList)
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
|
@ -3,9 +3,9 @@ import __init__
|
|||||||
|
|
||||||
import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re
|
import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
|
import numpy
|
||||||
|
|
||||||
from wx import glcanvas
|
from wx import glcanvas
|
||||||
import wx
|
|
||||||
try:
|
try:
|
||||||
import OpenGL
|
import OpenGL
|
||||||
OpenGL.ERROR_CHECKING = False
|
OpenGL.ERROR_CHECKING = False
|
||||||
@ -55,18 +55,15 @@ class ProjectObject(stl.stlModel):
|
|||||||
self.modelDisplayList = None
|
self.modelDisplayList = None
|
||||||
self.modelDirty = False
|
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.getMinimumZ()
|
||||||
|
|
||||||
self.centerX = -self.getMinimum().x + 5
|
self.centerX = -self.getMinimum()[0] + 5
|
||||||
self.centerY = -self.getMinimum().y + 5
|
self.centerY = -self.getMinimum()[1] + 5
|
||||||
|
|
||||||
self.updateModelTransform()
|
self.updateModelTransform()
|
||||||
|
|
||||||
self.centerX = -self.getMinimum().x + 5
|
self.centerX = -self.getMinimum()[0] + 5
|
||||||
self.centerY = -self.getMinimum().y + 5
|
self.centerY = -self.getMinimum()[1] + 5
|
||||||
|
|
||||||
def isSameExceptForPosition(self, other):
|
def isSameExceptForPosition(self, other):
|
||||||
if self.filename != other.filename:
|
if self.filename != other.filename:
|
||||||
@ -96,10 +93,7 @@ class ProjectObject(stl.stlModel):
|
|||||||
minZ = self.getMinimumZ()
|
minZ = self.getMinimumZ()
|
||||||
minV = self.getMinimum()
|
minV = self.getMinimum()
|
||||||
maxV = self.getMaximum()
|
maxV = self.getMaximum()
|
||||||
for v in self.vertexes:
|
self.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])
|
||||||
v.z -= minZ
|
|
||||||
v.x -= minV.x + (maxV.x - minV.x) / 2
|
|
||||||
v.y -= minV.y + (maxV.y - minV.y) / 2
|
|
||||||
minZ = self.getMinimumZ()
|
minZ = self.getMinimumZ()
|
||||||
self.modelDirty = True
|
self.modelDirty = True
|
||||||
|
|
||||||
@ -125,14 +119,14 @@ class ProjectObject(stl.stlModel):
|
|||||||
return p
|
return p
|
||||||
|
|
||||||
def clampXY(self):
|
def clampXY(self):
|
||||||
if self.centerX < -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x:
|
if self.centerX < -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]:
|
||||||
self.centerX = -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x
|
self.centerX = -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]
|
||||||
if self.centerY < -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y:
|
if self.centerY < -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]:
|
||||||
self.centerY = -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y
|
self.centerY = -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]
|
||||||
if self.centerX > self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale:
|
if self.centerX > self.parent.machineSize[0] + self.parent.extruderOffset[self.extruder][0] - self.getMaximum()[0] * self.scale:
|
||||||
self.centerX = self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * 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.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * 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.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale
|
self.centerY = self.parent.machineSize[1] + self.parent.extruderOffset[self.extruder][1] - self.getMaximum()[1] * self.scale
|
||||||
|
|
||||||
class projectPlanner(wx.Frame):
|
class projectPlanner(wx.Frame):
|
||||||
"Main user interface window"
|
"Main user interface window"
|
||||||
@ -151,15 +145,15 @@ class projectPlanner(wx.Frame):
|
|||||||
self.selection = None
|
self.selection = None
|
||||||
self.printMode = 0
|
self.printMode = 0
|
||||||
|
|
||||||
self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height'))
|
self.machineSize = numpy.array([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.headSizeMin = numpy.array([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.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
|
||||||
|
|
||||||
self.extruderOffset = [
|
self.extruderOffset = [
|
||||||
util3d.Vector3(0,0,0),
|
numpy.array([0,0,0]),
|
||||||
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0),
|
numpy.array([profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0]),
|
||||||
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0),
|
numpy.array([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([profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0])]
|
||||||
|
|
||||||
self.toolbar = toolbarUtil.Toolbar(self.panel)
|
self.toolbar = toolbarUtil.Toolbar(self.panel)
|
||||||
|
|
||||||
@ -392,7 +386,7 @@ class projectPlanner(wx.Frame):
|
|||||||
|
|
||||||
def OnTopClick(self):
|
def OnTopClick(self):
|
||||||
self.preview.view3D = False
|
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.offsetX = 0
|
||||||
self.preview.offsetY = 0
|
self.preview.offsetY = 0
|
||||||
self.preview.Refresh()
|
self.preview.Refresh()
|
||||||
@ -499,9 +493,9 @@ class projectPlanner(wx.Frame):
|
|||||||
self.listbox.SetSelection(-1)
|
self.listbox.SetSelection(-1)
|
||||||
|
|
||||||
def OnAutoPlace(self, e):
|
def OnAutoPlace(self, e):
|
||||||
bestAllowedSize = int(self.machineSize.y)
|
bestAllowedSize = int(self.machineSize[1])
|
||||||
bestArea = self._doAutoPlace(bestAllowedSize)
|
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)
|
area = self._doAutoPlace(i)
|
||||||
if area < bestArea:
|
if area < bestArea:
|
||||||
bestAllowedSize = i
|
bestAllowedSize = i
|
||||||
@ -516,18 +510,18 @@ class projectPlanner(wx.Frame):
|
|||||||
extraSizeMax = self.headSizeMax
|
extraSizeMax = self.headSizeMax
|
||||||
if profile.getProfileSettingFloat('skirt_line_count') > 0:
|
if profile.getProfileSettingFloat('skirt_line_count') > 0:
|
||||||
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
|
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
|
||||||
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0)
|
extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
|
||||||
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0)
|
extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
|
||||||
if profile.getProfileSetting('support') != 'None':
|
if profile.getProfileSetting('support') != 'None':
|
||||||
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0)
|
extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
|
||||||
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0)
|
extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
|
||||||
|
|
||||||
if self.printMode == 1:
|
if self.printMode == 1:
|
||||||
extraSizeMin = util3d.Vector3(6.0, 6.0, 0)
|
extraSizeMin = numpy.array([6.0, 6.0, 0])
|
||||||
extraSizeMax = util3d.Vector3(6.0, 6.0, 0)
|
extraSizeMax = numpy.array([6.0, 6.0, 0])
|
||||||
|
|
||||||
if extraSizeMin.x > extraSizeMax.x:
|
if extraSizeMin[0] > extraSizeMax[0]:
|
||||||
posX = self.machineSize.x
|
posX = self.machineSize[0]
|
||||||
dirX = -1
|
dirX = -1
|
||||||
else:
|
else:
|
||||||
posX = 0
|
posX = 0
|
||||||
@ -535,35 +529,35 @@ class projectPlanner(wx.Frame):
|
|||||||
posY = 0
|
posY = 0
|
||||||
dirY = 1
|
dirY = 1
|
||||||
|
|
||||||
minX = self.machineSize.x
|
minX = self.machineSize[0]
|
||||||
minY = self.machineSize.y
|
minY = self.machineSize[1]
|
||||||
maxX = 0
|
maxX = 0
|
||||||
maxY = 0
|
maxY = 0
|
||||||
for item in self.list:
|
for item in self.list:
|
||||||
item.centerX = posX + item.getMaximum().x * item.scale * dirX
|
item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
|
||||||
item.centerY = posY + item.getMaximum().y * item.scale * dirY
|
item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
|
||||||
if item.centerY + item.getSize().y >= allowedSizeY:
|
if item.centerY + item.getSize()[1] >= allowedSizeY:
|
||||||
if dirX < 0:
|
if dirX < 0:
|
||||||
posX = minX - extraSizeMax.x - 1
|
posX = minX - extraSizeMax[0] - 1
|
||||||
else:
|
else:
|
||||||
posX = maxX + extraSizeMin.x + 1
|
posX = maxX + extraSizeMin[0] + 1
|
||||||
posY = 0
|
posY = 0
|
||||||
item.centerX = posX + item.getMaximum().x * item.scale * dirX
|
item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
|
||||||
item.centerY = posY + item.getMaximum().y * item.scale * dirY
|
item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
|
||||||
posY += item.getSize().y * item.scale * dirY + extraSizeMin.y + 1
|
posY += item.getSize()[1] * item.scale * dirY + extraSizeMin[1] + 1
|
||||||
minX = min(minX, item.centerX - item.getSize().x * item.scale / 2)
|
minX = min(minX, item.centerX - item.getSize()[0] * item.scale / 2)
|
||||||
minY = min(minY, item.centerY - item.getSize().y * item.scale / 2)
|
minY = min(minY, item.centerY - item.getSize()[1] * item.scale / 2)
|
||||||
maxX = max(maxX, item.centerX + item.getSize().x * item.scale / 2)
|
maxX = max(maxX, item.centerX + item.getSize()[0] * item.scale / 2)
|
||||||
maxY = max(maxY, item.centerY + item.getSize().y * item.scale / 2)
|
maxY = max(maxY, item.centerY + item.getSize()[1] * item.scale / 2)
|
||||||
|
|
||||||
for item in self.list:
|
for item in self.list:
|
||||||
if dirX < 0:
|
if dirX < 0:
|
||||||
item.centerX -= minX / 2
|
item.centerX -= minX / 2
|
||||||
else:
|
else:
|
||||||
item.centerX += (self.machineSize.x - maxX) / 2
|
item.centerX += (self.machineSize[0] - maxX) / 2
|
||||||
item.centerY += (self.machineSize.y - maxY) / 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)) * 100
|
||||||
|
|
||||||
return (maxX - minX) + (maxY - minY)
|
return (maxX - minX) + (maxY - minY)
|
||||||
@ -590,8 +584,8 @@ class projectPlanner(wx.Frame):
|
|||||||
for item in self.list:
|
for item in self.list:
|
||||||
if item.profile != None and os.path.isfile(item.profile):
|
if item.profile != None and os.path.isfile(item.profile):
|
||||||
profile.loadGlobalProfile(item.profile)
|
profile.loadGlobalProfile(item.profile)
|
||||||
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder].x)
|
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder][0])
|
||||||
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder].y)
|
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder][1])
|
||||||
put('model_scale', item.scale)
|
put('model_scale', item.scale)
|
||||||
put('flip_x', item.flipX)
|
put('flip_x', item.flipX)
|
||||||
put('flip_y', item.flipY)
|
put('flip_y', item.flipY)
|
||||||
@ -607,7 +601,7 @@ class projectPlanner(wx.Frame):
|
|||||||
action.temperature = profile.getProfileSettingFloat('print_temperature')
|
action.temperature = profile.getProfileSettingFloat('print_temperature')
|
||||||
action.extruder = item.extruder
|
action.extruder = item.extruder
|
||||||
action.filename = item.filename
|
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.clearZ = clearZ
|
||||||
action.leaveResultForNextSlice = False
|
action.leaveResultForNextSlice = False
|
||||||
action.usePreviousSlice = False
|
action.usePreviousSlice = False
|
||||||
@ -698,7 +692,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
|||||||
wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
|
wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
|
||||||
self.yaw = 30
|
self.yaw = 30
|
||||||
self.pitch = 60
|
self.pitch = 60
|
||||||
self.zoom = self.parent.machineSize.x / 2 + 10
|
self.zoom = self.parent.machineSize[0] / 2 + 10
|
||||||
self.offsetX = 0
|
self.offsetX = 0
|
||||||
self.offsetY = 0
|
self.offsetY = 0
|
||||||
self.view3D = False
|
self.view3D = False
|
||||||
@ -760,32 +754,30 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
|||||||
glTranslate(0,0,-self.zoom)
|
glTranslate(0,0,-self.zoom)
|
||||||
glRotate(-self.pitch, 1,0,0)
|
glRotate(-self.pitch, 1,0,0)
|
||||||
glRotate(self.yaw, 0,0,1)
|
glRotate(self.yaw, 0,0,1)
|
||||||
if False: #self.parent.triangleMesh != None:
|
|
||||||
glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)
|
|
||||||
else:
|
else:
|
||||||
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
||||||
glTranslate(self.offsetX, self.offsetY, 0.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.OnDraw()
|
||||||
self.SwapBuffers()
|
self.SwapBuffers()
|
||||||
|
|
||||||
def OnDraw(self):
|
def OnDraw(self):
|
||||||
machineSize = self.parent.machineSize
|
machineSize = self.parent.machineSize
|
||||||
opengl.DrawMachine(machineSize)
|
opengl.DrawMachine(util3d.Vector3(machineSize[0], machineSize[1], machineSize[2]))
|
||||||
extraSizeMin = self.parent.headSizeMin
|
extraSizeMin = self.parent.headSizeMin
|
||||||
extraSizeMax = self.parent.headSizeMax
|
extraSizeMax = self.parent.headSizeMax
|
||||||
if profile.getProfileSettingFloat('skirt_line_count') > 0:
|
if profile.getProfileSettingFloat('skirt_line_count') > 0:
|
||||||
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
|
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
|
||||||
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0)
|
extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
|
||||||
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0)
|
extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
|
||||||
if profile.getProfileSetting('support') != 'None':
|
if profile.getProfileSetting('support') != 'None':
|
||||||
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0)
|
extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
|
||||||
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0)
|
extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
|
||||||
|
|
||||||
if self.parent.printMode == 1:
|
if self.parent.printMode == 1:
|
||||||
extraSizeMin = util3d.Vector3(6.0, 6.0, 0)
|
extraSizeMin = numpy.array([6.0, 6.0, 0])
|
||||||
extraSizeMax = util3d.Vector3(6.0, 6.0, 0)
|
extraSizeMax = numpy.array([6.0, 6.0, 0])
|
||||||
|
|
||||||
for item in self.parent.list:
|
for item in self.parent.list:
|
||||||
item.validPlacement = True
|
item.validPlacement = True
|
||||||
@ -793,13 +785,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
|||||||
|
|
||||||
for idx1 in xrange(0, len(self.parent.list)):
|
for idx1 in xrange(0, len(self.parent.list)):
|
||||||
item = self.parent.list[idx1]
|
item = self.parent.list[idx1]
|
||||||
iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - extraSizeMin - 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 + util3d.Vector3(item.centerX, item.centerY, 0) + extraSizeMax - 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):
|
for idx2 in xrange(0, idx1):
|
||||||
item2 = self.parent.list[idx2]
|
item2 = self.parent.list[idx2]
|
||||||
iMin2 = item2.getMinimum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)
|
iMin2 = (item2.getMinimum() * item2.scale) + numpy.array([item2.centerX, item2.centerY, 0])
|
||||||
iMax2 = item2.getMaximum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)
|
iMax2 = (item2.getMaximum() * item2.scale) + numpy.array([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:
|
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
|
item.validPlacement = False
|
||||||
item2.gotHit = True
|
item2.gotHit = True
|
||||||
|
|
||||||
@ -959,8 +951,8 @@ class ProjectSliceProgressWindow(wx.Frame):
|
|||||||
line = p.stdout.readline()
|
line = p.stdout.readline()
|
||||||
self.returnCode = p.wait()
|
self.returnCode = p.wait()
|
||||||
|
|
||||||
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x)
|
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder][0])
|
||||||
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y)
|
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder][1])
|
||||||
put('clear_z', action.clearZ)
|
put('clear_z', action.clearZ)
|
||||||
put('extruder', action.extruder)
|
put('extruder', action.extruder)
|
||||||
put('print_temperature', action.temperature)
|
put('print_temperature', action.temperature)
|
||||||
@ -1089,8 +1081,8 @@ class preferencesDialog(configBase.configWindowBase):
|
|||||||
self.Fit()
|
self.Fit()
|
||||||
|
|
||||||
def OnClose(self, e):
|
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.headSizeMin = numpy.array([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.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
|
||||||
self.parent.Refresh()
|
self.parent.Refresh()
|
||||||
|
|
||||||
self.MakeModal(False)
|
self.MakeModal(False)
|
||||||
|
@ -2,41 +2,36 @@ import sys, math, re, os, struct, time
|
|||||||
|
|
||||||
import util3d
|
import util3d
|
||||||
|
|
||||||
class meshFace(object):
|
import numpy
|
||||||
def __init__(self, v0, v1, v2):
|
|
||||||
self.v = [v0, v1, v2]
|
|
||||||
|
|
||||||
class mesh(object):
|
class mesh(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.faces = []
|
self.vertexes = None
|
||||||
self.vertexes = []
|
self.origonalVertexes = None
|
||||||
|
self.vertexCount = 0
|
||||||
|
|
||||||
def addFace(self, v0, v1, v2):
|
def addVertex(self, x, y, z):
|
||||||
self.vertexes.append(v0)
|
n = self.vertexCount
|
||||||
self.vertexes.append(v1)
|
self.origonalVertexes[n][0] = x
|
||||||
self.vertexes.append(v2)
|
self.origonalVertexes[n][1] = y
|
||||||
self.faces.append(meshFace(v0, v1, v2))
|
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):
|
def _postProcessAfterLoad(self):
|
||||||
self.origonalVertexes = list(self.vertexes)
|
self.vertexes = self.origonalVertexes.copy()
|
||||||
for i in xrange(0, len(self.origonalVertexes)):
|
|
||||||
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
|
|
||||||
self.getMinimumZ()
|
self.getMinimumZ()
|
||||||
|
|
||||||
def getMinimumZ(self):
|
def getMinimumZ(self):
|
||||||
minv = self.vertexes[0].copy()
|
self.min = self.vertexes.min(0)
|
||||||
maxv = self.vertexes[0].copy()
|
self.max = self.vertexes.max(0)
|
||||||
for v in self.vertexes:
|
self.size = self.max - self.min
|
||||||
minv.x = min(minv.x, v.x)
|
return self.min[2]
|
||||||
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
|
|
||||||
|
|
||||||
def getMaximum(self):
|
def getMaximum(self):
|
||||||
return self.max
|
return self.max
|
||||||
@ -62,23 +57,23 @@ class mesh(object):
|
|||||||
mat11 = math.cos(rotate) * scaleY
|
mat11 = math.cos(rotate) * scaleY
|
||||||
|
|
||||||
for i in xrange(0, len(self.origonalVertexes)):
|
for i in xrange(0, len(self.origonalVertexes)):
|
||||||
x = self.origonalVertexes[i].x
|
x = self.origonalVertexes[i][0]
|
||||||
y = self.origonalVertexes[i].y
|
y = self.origonalVertexes[i][1]
|
||||||
z = self.origonalVertexes[i].z
|
z = self.origonalVertexes[i][2]
|
||||||
if swapXZ:
|
if swapXZ:
|
||||||
x, z = z, x
|
x, z = z, x
|
||||||
if swapYZ:
|
if swapYZ:
|
||||||
y, z = z, y
|
y, z = z, y
|
||||||
self.vertexes[i].x = x * mat00 + y * mat01
|
self.vertexes[i][0] = x * mat00 + y * mat01
|
||||||
self.vertexes[i].y = x * mat10 + y * mat11
|
self.vertexes[i][1] = x * mat10 + y * mat11
|
||||||
self.vertexes[i].z = z * scaleZ
|
self.vertexes[i][2] = z * scaleZ
|
||||||
|
|
||||||
for face in self.faces:
|
for i in xrange(0, len(self.origonalVertexes), 3):
|
||||||
v1 = face.v[0]
|
v1 = self.vertexes[i]
|
||||||
v2 = face.v[1]
|
v2 = self.vertexes[i+1]
|
||||||
v3 = face.v[2]
|
v3 = self.vertexes[i+2]
|
||||||
face.normal = (v2 - v1).cross(v3 - v1)
|
self.normal[i/3] = numpy.cross((v2 - v1), (v3 - v1))
|
||||||
face.normal.normalize()
|
self.normal[i/3] /= (self.normal[i/3] * self.normal[i/3]).sum()
|
||||||
|
|
||||||
self.getMinimumZ()
|
self.getMinimumZ()
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import sys, math, re, os, struct, time
|
import sys, math, re, os, struct, time
|
||||||
|
|
||||||
import util3d
|
|
||||||
import mesh
|
import mesh
|
||||||
|
|
||||||
class stlModel(mesh.mesh):
|
class stlModel(mesh.mesh):
|
||||||
@ -11,7 +10,7 @@ class stlModel(mesh.mesh):
|
|||||||
f = open(filename, "rb")
|
f = open(filename, "rb")
|
||||||
if f.read(5).lower() == "solid":
|
if f.read(5).lower() == "solid":
|
||||||
self._loadAscii(f)
|
self._loadAscii(f)
|
||||||
if not self.faces:
|
if self.vertexCount < 3:
|
||||||
f.seek(5, os.SEEK_SET)
|
f.seek(5, os.SEEK_SET)
|
||||||
self._loadBinary(f)
|
self._loadBinary(f)
|
||||||
else:
|
else:
|
||||||
@ -22,31 +21,28 @@ class stlModel(mesh.mesh):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def _loadAscii(self, f):
|
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
|
cnt = 0
|
||||||
for line in f:
|
for line in f:
|
||||||
if 'vertex' in line:
|
if 'vertex' in line:
|
||||||
data = line.split()
|
data = line.split()
|
||||||
if cnt == 0:
|
self.addVertex(float(data[1]), float(data[2]), float(data[3]))
|
||||||
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
|
|
||||||
|
|
||||||
def _loadBinary(self, f):
|
def _loadBinary(self, f):
|
||||||
#Skip the header
|
#Skip the header
|
||||||
f.read(80-5)
|
f.read(80-5)
|
||||||
faceCount = struct.unpack('<I', f.read(4))[0]
|
faceCount = struct.unpack('<I', f.read(4))[0]
|
||||||
|
self._prepareVertexCount(faceCount * 3)
|
||||||
for idx in xrange(0, faceCount):
|
for idx in xrange(0, faceCount):
|
||||||
data = struct.unpack("<ffffffffffffH", f.read(50))
|
data = struct.unpack("<ffffffffffffH", f.read(50))
|
||||||
v0 = util3d.Vector3(data[3], data[4], data[5])
|
self.addVertex(data[3], data[4], data[5])
|
||||||
v1 = util3d.Vector3(data[6], data[7], data[8])
|
self.addVertex(data[6], data[7], data[8])
|
||||||
v2 = util3d.Vector3(data[9], data[10], data[11])
|
self.addVertex(data[9], data[10], data[11])
|
||||||
self.addFace(v0, v1, v2)
|
|
||||||
|
|
||||||
def saveAsSTL(mesh, filename):
|
def saveAsSTL(mesh, filename):
|
||||||
f = open(filename, 'wb')
|
f = open(filename, 'wb')
|
||||||
@ -70,8 +66,8 @@ def saveAsSTL(mesh, filename):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
for filename in sys.argv[1:]:
|
for filename in sys.argv[1:]:
|
||||||
m = stlModel().load(filename)
|
m = stlModel().load(filename)
|
||||||
print("Loaded %d faces" % (len(m.faces)))
|
print("Loaded %d faces" % (m.vertexCount / 3))
|
||||||
parts = m.splitToParts()
|
# parts = m.splitToParts()
|
||||||
for p in parts:
|
# for p in parts:
|
||||||
saveAsSTL(p, "export_%i.stl" % parts.index(p))
|
# saveAsSTL(p, "export_%i.stl" % parts.index(p))
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class Vector3(object):
|
|||||||
return Vector3(self.x, self.y, self.z)
|
return Vector3(self.x, self.y, self.z)
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __add__(self, v):
|
||||||
return Vector3( self.x + v.x, self.y + v.y, self.z + v.z )
|
return Vector3( self.x + v.x, self.y + v.y, self.z + v.z )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user