Merge branch 'master' into HEAD

git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5425 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
jriegel
2012-01-24 19:15:53 +00:00
104 changed files with 24184 additions and 301 deletions

View File

@@ -1027,6 +1027,8 @@ src/Mod/TemplatePyMod/Makefile
src/Mod/Sandbox/Makefile
src/Mod/Sandbox/App/Makefile
src/Mod/Sandbox/Gui/Makefile
src/Mod/Surfaces/Makefile
src/Mod/Ship/Makefile
src/Tools/Makefile
src/Tools/_TEMPLATE_/Makefile
src/Tools/_TEMPLATE_/App/Makefile

View File

@@ -22,6 +22,7 @@
#***************************************************************************
import FreeCAD,FreeCADGui,Draft,math
from draftlibs import fcvec
from FreeCAD import Vector
from PyQt4 import QtCore, QtGui

View File

@@ -89,30 +89,28 @@ class _Cell(ArchComponent.Component):
import Part
pl = obj.Placement
if obj.Components:
shapes = []
if obj.JoinMode:
walls = []
structs = []
compshapes = []
for comp in obj.Components:
if Draft.getType(comp) == "Wall":
walls.append(comp.Shape)
elif Draft.getType(comp) == "Structure":
structs.append(comp.Shape)
for c in obj.Components:
if Draft.getType(c) == "Wall":
walls.append(c.Shape)
elif Draft.getType(c) == "Structure":
structs.append(c.Shape)
else:
compshapes.append(comp.Shape)
for gr in [walls,structs]:
if gr:
sh = gr.pop(0)
for csh in gr:
sh = sh.oldFuse(csh)
compshapes.append(sh)
baseShape = Part.makeCompound(compshapes)
shapes.append(c.Shape)
for group in [walls,structs]:
if group:
sh = group.pop(0).copy()
for subsh in group:
sh = sh.oldFuse(subsh)
shapes.append(sh)
else:
compshapes = []
for o in obj.Components:
compshapes.append(o.Shape)
baseShape = Part.makeCompound(compshapes)
obj.Shape = baseShape
for c in obj.Components:
shapes.append(c.Shape)
if shapes:
obj.Shape = Part.makeCompound(shapes)
obj.Placement = pl
class _ViewProviderCell(ArchComponent.ViewProviderComponent):

View File

@@ -138,6 +138,7 @@ def splitMesh(obj,mark=True):
def meshToShape(obj,mark=True):
'''meshToShape(object,[mark]): turns a mesh into a shape, joining coplanar facets. If
mark is True (default), non-solid objects will be marked in red'''
name = obj.Name
import Part,MeshPart
from draftlibs import fcgeo
@@ -259,6 +260,24 @@ def mergeCells(objectslist):
FreeCAD.ActiveDocument.removeObject(o.Name)
FreeCAD.ActiveDocument.recompute()
return base
def download(url):
'''downloads a file from the given URL and saves it in the
user directory. Returns the path to the saved file'''
try:
FreeCAD.Console.PrintMessage("downloading "+url+" ...\n")
import urllib2, os
response = urllib2.urlopen(url)
s = response.read()
fp = os.path.join(FreeCAD.ConfigGet("UserAppData"),url.split('/')[-1])
if not os.path.exists(fp):
f = open(fp,'wb')
f.write(s)
f.close()
except:
return None
else:
return fp
# command definitions ###############################################

View File

@@ -59,13 +59,42 @@ class _CommandWall:
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
done = False
if sel:
FreeCAD.ActiveDocument.openTransaction("Wall")
for obj in sel:
makeWall(obj)
FreeCAD.ActiveDocument.commitTransaction()
else:
wall = makeWall()
import Draft
if Draft.getType(sel[0]) != "Wall":
FreeCAD.ActiveDocument.openTransaction("Wall")
for obj in sel:
makeWall(obj)
FreeCAD.ActiveDocument.commitTransaction()
done = True
if not done:
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
FreeCADGui.Snapper.getPoint(callback=self.getPoint)
def getPoint(self,point):
"this function is called by the snapper when it has a 3D point"
if point == None:
self.tracker.finalize()
return
self.points.append(point)
if len(self.points) == 1:
self.tracker.on()
FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update)
elif len(self.points) == 2:
import Draft
l = Draft.makeWire(self.points)
makeWall(l)
self.tracker.finalize()
def update(self,point):
"this function is called by the Snapper when the mouse is moved"
self.tracker.update([self.points[0],point])
class _Wall(ArchComponent.Component):
"The Wall object"

View File

@@ -2,7 +2,7 @@
# Resource object code
#
# Created: Tue Jan 17 17:15:03 2012
# Created: Tue Jan 24 10:12:37 2012
# by: The Resource Compiler for PyQt (Qt v4.7.4)
#
# WARNING! All changes made in this file will be lost!
@@ -5697,122 +5697,83 @@ qt_resource_data = "\
\x00\x00\x00\x12\x00\x57\x00\x65\x00\x72\x00\x6b\x00\x7a\x00\x65\
\x00\x75\x00\x67\x00\x65\x08\x00\x00\x00\x00\x06\x00\x00\x00\x05\
\x54\x6f\x6f\x6c\x73\x07\x00\x00\x00\x04\x61\x72\x63\x68\x01\
\x00\x00\x07\x1c\
\x00\x00\x04\xaa\
\x00\
\x00\x27\x43\x78\x9c\xed\x5a\x6d\x73\xda\x38\x10\xfe\x9e\x5f\xa1\
\xe3\x66\xda\xbb\x99\x80\x21\x81\x34\x21\xc6\x9d\x96\x24\x4d\x66\
\xd2\x2b\x2d\xb4\x99\xfb\xd4\x31\xb6\xc0\x6a\x65\xcb\xb1\xe4\x1a\
\x7a\x73\xff\xfd\x56\x92\x0d\x36\x06\xf2\x02\x49\xae\x9d\xce\x24\
\x13\x4b\xbb\xda\x5d\xad\x76\x9f\x5d\x39\x36\x5f\x4e\x7c\x8a\xbe\
\xe1\x88\x13\x16\x74\x2a\x8d\x5a\xbd\x82\x70\xe0\x30\x97\x04\xe3\
\x4e\xe5\xe3\xe0\xac\x7a\x58\x79\x69\xed\x98\x31\x99\x33\x35\x81\
\xc9\xda\x41\xa6\x43\x6d\xce\xad\x37\x31\x69\xb7\x4f\x88\x4d\xd9\
\x18\xfe\xd2\x71\x1f\x0b\x01\x8b\xf9\xab\xc8\xf1\x4c\x43\xf3\x00\
\x73\x42\xdc\x31\x16\x48\x8d\x3b\x95\xf7\x57\x6a\x58\x41\x81\xed\
\xe3\x4e\x65\x9d\x0c\xa9\x0a\x99\x61\xc4\x42\x1c\x89\x69\xba\x60\
\x8c\x99\x8f\x45\x34\x55\x44\x64\x46\xd8\x11\xea\x09\x99\x13\xab\
\x6e\x1a\x93\x74\x30\x95\x83\x69\x3a\x00\x0b\x84\x67\xb5\x5e\xb4\
\x4c\x43\x3f\xea\x69\x0f\x93\xb1\x27\xac\x83\xbd\x23\xd3\x48\x9f\
\x95\x4c\x23\x13\x6a\x1a\x99\xf2\x65\x96\x24\x24\x70\x59\x32\x20\
\x82\xe2\xd4\x18\x2e\x22\xb0\xdd\x7a\x83\x03\x1c\xd9\x14\xf1\x74\
\x2f\xa6\x91\x12\xca\x22\xa9\x3d\x65\xf1\xdc\x37\x9f\x5e\xb3\xc9\
\xa5\x9a\x4a\x25\x2e\xa8\xe4\xa1\xed\x80\xa0\x4a\xba\x81\x20\xf6\
\x87\x38\xb2\x0e\x4c\x23\x7d\xd2\xe6\xe7\x35\x94\x44\xf8\x76\x34\
\x26\xc1\x82\x84\xa3\xb5\x12\x88\xc0\xfe\xdc\x93\xf9\xb3\x7c\x13\
\xb1\x38\x04\x9b\xb3\xd3\x1c\x67\x63\xcd\x5e\x52\x2e\xe6\xce\x5a\
\xe2\x2f\x79\xe6\xa8\xbf\xc4\x69\x65\x9b\xd6\xba\x2e\x55\x06\x51\
\x2b\x88\x63\x53\x3d\xfb\x79\x6f\xae\x77\xbe\xa1\x25\x82\xce\x4b\
\x82\x3c\x16\x91\xef\x2c\x10\x4b\x44\x2d\x0a\x2b\xbb\xe8\xd2\x1e\
\x62\x9a\x49\xa2\x72\x50\x58\xbe\xc4\x47\x78\x22\x0a\x0c\x33\x3f\
\x9d\xe0\x91\x1d\x53\x10\xcd\x28\x8b\xd0\x08\x7e\x13\x9b\xd2\x45\
\x4f\x2d\x77\x97\x9e\xd4\xb6\xe5\x8c\x37\x8a\xd6\x97\x36\x23\x03\
\x0e\x47\x25\x3f\xf4\xd5\xf4\xda\x6d\x00\x2f\x06\x56\x01\xb8\xb1\
\xb0\x1b\x0c\xa1\x66\xbd\x17\xed\xf6\xf9\x4c\x9e\x69\xa8\xc9\x9b\
\x36\x50\xce\x07\xf2\x1d\x9f\x93\x00\x4e\x8a\x0b\x17\xd2\xad\x53\
\xa9\x2f\xba\x0e\x38\x0a\x33\x19\x1a\x34\xeb\x05\x30\x98\x51\x53\
\x20\xd8\xab\x17\x30\x61\x6e\xd6\xa2\xc0\x15\x9e\xd6\x8e\xbb\x83\
\xa7\x8b\x61\xa3\x60\xb1\x17\xe1\x51\x57\x9e\xf5\xeb\x58\x08\x70\
\x63\x96\x64\x92\x16\x02\x4d\xc5\xc1\x50\xd3\xd6\x46\x14\x63\x74\
\x40\xc2\xe5\x41\x35\xf0\x08\x47\xf0\x23\x3c\x8c\xdc\x52\x80\x05\
\x38\x41\x57\x10\x64\x88\x0d\xbf\x00\x28\xde\x3e\xd6\x4a\x46\x28\
\x99\x0b\x26\xa8\xb9\x05\xff\x47\xd8\xb5\xf6\x5a\x2d\x09\xc2\xee\
\x02\x69\x1c\x61\x1c\x58\x8d\x23\x38\x1a\xfd\x58\x24\x0f\x69\x8c\
\xad\xc6\x0b\xa0\xaa\xa7\xe2\xb1\x95\x54\xdd\xce\x6a\xe9\xe6\xd3\
\x40\x96\x9b\x95\x11\xe6\xa4\x1e\x91\x6e\x52\xa7\x05\xca\xee\xeb\
\x24\xa9\xae\x67\x0b\xef\x66\x6d\x6f\x99\x6b\xa4\x75\x76\x5b\xd9\
\x6f\x1a\x1a\x09\x67\x30\x59\x20\x6f\x0a\x9a\x1b\x41\xe6\xd6\x00\
\x13\x08\xb1\x23\xe2\x08\x3f\x1d\x6a\xde\x00\xff\xbf\x70\xf3\x31\
\x71\xf3\xa6\x5a\xbc\x19\x72\xf6\xb3\x68\x7b\x5c\xf8\x6c\xb4\xea\
\x6b\xe0\xf3\xe0\x68\x1d\x7c\x1e\x1e\x3c\x11\x7c\xce\x7c\xf5\x0b\
\x43\x57\x37\x9e\x07\x9b\x35\x9e\xad\xed\x35\x9e\xea\xee\xf3\x84\
\x20\xda\xfc\x05\xa2\xab\x7d\xfd\xd8\x20\xba\xbf\xf6\x30\xee\x02\
\x5d\xad\xa3\x35\xc8\xb5\xbf\xb7\x0e\xb9\x9a\x4f\x85\x5c\x57\x2a\
\x17\x7e\x5e\xd8\x2a\x12\x0b\xb2\x72\x7c\xf7\x78\x4b\x30\x2f\xbe\
\xb7\x7b\x4f\x70\x71\xd6\x45\xc4\x0f\x59\x24\xb6\xfd\x72\x60\x7b\
\xaf\x06\xf6\x37\x43\xe8\xf5\x99\xb4\x1a\xa1\x9f\x51\x71\xfc\xdb\
\xc9\xbb\xee\xe0\xef\xde\x29\x3a\x1f\xbc\xbd\x44\xbd\x8f\xaf\x2f\
\x2f\xba\xe8\xd9\x75\xcc\xc4\x71\xd5\x30\xae\xf6\xbb\x86\x71\x32\
\x38\xd1\xd4\x66\xad\x6e\x18\xa7\x7f\x69\x6a\xca\xe4\x09\x11\xb6\
\x0d\x23\x49\x92\x5a\xb2\x5f\x63\xd1\xd8\x18\x7c\x30\x3e\x9c\x76\
\xab\x9e\xf0\x69\xb3\xae\x5c\xee\x88\x9a\x2b\x5c\xcd\xff\x6c\x2c\
\x8e\x77\xa4\x62\x49\x97\x03\xf5\x8c\x6d\x37\x7b\xf6\xb1\xb0\xb5\
\xe5\x7a\xc1\x35\xac\xf7\xe4\x1e\x52\xb5\x0e\x38\x0e\x60\x3a\xa5\
\x36\xd2\x59\x23\x5b\xce\xc5\x94\x62\x24\xa6\x61\xb6\x5e\x2e\x85\
\x98\xe7\x39\xf5\xe1\x2e\xa2\x04\xfd\x83\x12\x0f\x7c\x5d\x55\xb8\
\xd7\x46\x90\x4a\xd5\x24\xb2\xc3\x63\xf4\xaf\xb2\xcf\x50\x92\x32\
\xb1\x46\xde\xc4\x21\x73\xa7\x48\x91\x53\x1d\x50\xdd\x02\x51\x1d\
\xd9\x3e\xa1\xd3\xf6\xf3\x13\xfc\xc5\xfe\x14\xa3\xbe\x1d\xf0\xe7\
\x29\x49\x42\x70\xfb\x30\xcc\x38\x13\x05\xd3\xed\x66\xbd\x9e\xd1\
\xa5\xb0\x76\xc0\x22\xdf\xa6\xc7\x0b\x8e\x0a\x8b\xaa\xf4\xab\xb8\
\xaa\x60\x61\xbb\x1e\x4e\x66\xe3\x21\x03\x50\xf5\x0b\x53\x14\x8f\
\x44\x61\x22\x52\x5a\xd5\x4c\xf5\x5a\x54\x87\x94\x39\x5f\xab\x80\
\x43\xe0\xce\x36\x58\x22\x3d\x35\x1b\x02\xd3\xdc\x8e\x33\x28\xde\
\xb2\x61\x95\xb9\x14\x81\x23\xa0\xc2\x0a\x86\x46\x71\xe0\xc8\x62\
\xb9\x8b\x20\x88\xa1\x75\xc5\x2e\xb2\x03\xc5\xd3\x77\x3c\xec\xdb\
\xe8\x74\x02\x4e\xe5\x1c\x8d\x08\x1c\xc9\x1f\x35\x3c\x09\xff\x44\
\xf6\x37\x9b\x40\xd4\xc2\x84\x87\x23\xdc\x56\xbe\x0d\xff\x4f\x7b\
\x95\x66\xd8\xc8\x03\x60\xed\x94\x22\x9c\x0b\x1c\xca\xee\x9e\xd7\
\x1c\xe6\x1b\x3c\x0e\x25\xac\x40\xa0\xb8\xf8\xdb\x67\x97\x39\xdc\
\xc0\x7a\xc7\x06\x19\x39\x7b\x93\xfd\xf4\xcf\x67\xe1\x34\xe4\xe6\
\x8b\x3a\x20\xec\x82\xe2\x6e\x95\x4d\x2e\x76\x58\xa4\x7a\x90\x36\
\x8a\xc1\xbe\x88\x92\x00\x1f\xeb\x26\xaa\xfd\x7b\xab\x7e\x88\xdd\
\xc3\x9c\xb5\xdb\x33\x4e\x85\x3c\xd8\x34\x8b\x78\x7b\xf6\x14\xce\
\x9e\x64\xe4\xcf\x53\x22\xcd\xe0\xed\xf5\x73\x0f\xdc\x08\x37\x6f\
\x0f\xb3\xf3\x6e\xc6\xc3\xce\xd7\x7c\x19\x9a\xb5\x32\x92\x30\xcc\
\xd7\xa3\xe5\xe8\xbb\xee\x32\x48\x46\x90\x56\xfa\x3e\xa8\xc4\x61\
\x77\x57\xe5\x19\xf4\x87\x38\x0a\xb2\x97\xdb\x32\xa3\x42\x3b\xe2\
\x58\x76\xd0\x94\xa2\x21\x46\x31\xc7\x32\x03\x87\x31\xa1\xae\x66\
\x4a\xef\x8a\x68\x14\x31\x1f\x7d\x0d\x58\xa2\x33\x51\x02\x21\xaf\
\xdd\xff\x06\xb9\xba\x78\x48\x13\x66\x76\xce\x4d\xdc\xe0\xb2\xaa\
\x3d\xb0\xa0\x6d\x08\xfe\xb3\xe0\x96\x87\xa1\x4f\x93\x8f\x0f\xd9\
\x93\xc1\x96\x2e\x46\x4e\x2f\xdd\xc7\x8f\xd9\x94\xdd\xf5\x4a\xb4\
\xbe\x77\xf8\x75\x25\xda\xe4\x4a\xb4\xac\x57\x5b\x7f\x05\x5d\x9d\
\x6e\xb9\xb2\xaa\xca\x29\xd4\x33\x75\x2c\x0f\x79\x99\x5e\x01\x89\
\x67\xa0\xbf\xeb\x31\x06\x59\x52\x42\x45\x69\x9b\x93\xd2\xee\x0d\
\x8b\xdb\x6b\x37\x6a\x48\xca\xa2\xc4\xc1\x01\x07\xc9\x52\x1a\x67\
\x01\x47\x09\x46\x76\x84\x51\xc0\x04\xb2\x29\x65\x09\xc8\x02\x0d\
\xdc\x23\x21\x28\xb6\x85\x16\x91\x10\xe1\xa1\x33\xb8\x3a\x76\x5f\
\x9d\xec\x22\xce\x94\x5e\x3f\xe6\x02\xc1\xcd\x2d\xa0\xcc\x76\x11\
\x11\x72\x12\xf0\x82\x8e\x6a\xa8\x47\x21\x5a\x72\xeb\x09\xd4\x77\
\xe6\xcf\x8f\x0a\xc1\x8f\xe4\x86\x62\xee\x87\x31\x20\xe7\x2e\x6c\
\xc0\x45\xb0\x18\x90\x5b\x6d\x58\x2d\x93\x7d\xd1\x06\x88\x7d\x07\
\xbc\x03\xb0\xd3\xae\xfb\x51\xc1\xee\x81\xfb\x85\xd6\x43\xf4\x0b\
\xf7\x4f\x8b\x8b\x15\xdd\x02\xa4\xc0\xbb\x10\x07\x7d\x0f\x43\x73\
\xa0\xaf\xba\xc5\x56\xc1\x55\x6f\xdf\xb2\x0e\x41\x06\xbd\x07\x81\
\x47\x61\x7e\x38\x2d\xf6\x1b\x9b\xd6\xf0\xd5\xf8\xf5\x91\x17\x0d\
\x7d\x94\x00\xd7\x05\x3d\xa7\xf3\x27\x0c\xf3\x5b\xbd\x68\xc9\x31\
\xe5\x38\xd2\x94\xc8\xfe\x0d\x91\x7e\x27\xd2\xa9\x1c\x54\xd2\x5b\
\x54\xa7\xd2\x68\x54\x0c\xc9\x19\x92\x89\x6f\x87\x19\x04\x5b\xd7\
\x3d\x35\x3e\x83\x66\xf3\x2d\xf1\x71\x1f\x50\xcd\x81\x0e\x6d\x81\
\x4b\x7e\xf3\x03\x70\xc9\x7c\xad\x91\x2b\x4b\xf2\x33\xda\xca\xdc\
\x77\x41\xb9\xd2\x32\xff\x16\x48\x76\x1b\x13\xb8\xf3\xbb\xdc\x4a\
\xbf\x03\x82\x4e\x23\x9d\x50\x54\x4f\xd5\x08\x29\xc1\x90\x02\xf4\
\x87\x41\x35\xcf\x34\x52\x82\x72\xc0\xa2\xde\xf5\x86\xe4\x5e\x62\
\x2e\x37\xa4\x17\x73\x2f\xa3\xaf\x32\x46\x1b\xcb\x37\xb3\x64\xa1\
\xe2\x2e\xb5\xa6\xec\xbb\x55\x26\x49\x69\x5b\x33\xeb\x26\x27\x95\
\x3d\xf9\x38\x66\xa5\x10\xbc\xfc\xe0\xe6\xd4\xcd\x8d\x29\x4e\xa8\
\xef\xd6\xa0\x03\x51\xc9\xc0\x55\xda\x38\x2c\x08\xb0\x4a\x06\x39\
\x36\x8d\x98\x58\x3b\xff\x01\xea\x67\xa5\xfc\
\x00\x1c\xf4\x78\x9c\xed\x59\x6d\x6f\xa3\x38\x10\xfe\xde\x5f\x61\
\xf1\xf9\xae\x24\xd9\x24\xbb\xad\x08\xab\x7d\xb9\xbe\x48\xbb\xba\
\x54\xe9\x6e\x3f\xae\x08\x4c\x82\x6f\xc1\xe6\x8c\xb9\x24\xfb\xeb\
\xcf\x36\x26\x60\x20\xb4\x69\xb2\xad\x54\x55\x6a\x54\xdb\x63\x66\
\xc6\x8f\x67\x1e\x0f\xd8\x79\xbf\x8e\x23\xf4\x1f\xb0\x14\x53\x32\
\xb1\xfa\xa7\x3d\x0b\x01\xf1\x69\x80\xc9\x72\x62\x7d\xbb\xbd\xf8\
\xf3\x9d\xf5\xde\x3d\x71\x32\x5c\x4e\x1a\x8a\x49\xee\x09\x72\xfc\
\xc8\x4b\x53\xf7\x32\xc3\xe7\xe7\x9f\xb1\x17\xd1\xa5\xf8\x1f\x2d\
\x67\xc0\xb9\x78\x38\xfd\xc0\xfc\xd0\xb1\xf3\x39\x62\xf2\x0a\x07\
\x4b\xe0\x48\xf5\x27\xd6\xcd\x9d\xea\x5a\x88\x78\x31\x4c\xac\x2e\
\x1d\xd2\x14\x72\x12\x46\x13\x60\x7c\xa3\x1f\x58\x02\x8d\x81\xb3\
\x8d\x12\x22\x87\x81\xcf\x55\x0b\x39\x6b\xb7\xe7\xd8\x6b\xdd\xd9\
\xc8\xce\x46\x77\x84\x07\x3c\x74\x47\x6f\x47\x8e\x9d\x37\xf3\xe1\
\x10\xf0\x32\xe4\xee\x78\x70\xe6\xd8\xba\xad\x74\xda\x85\x52\xc7\
\x2e\x8c\xb7\x79\xb2\xc2\x24\xa0\xab\x5b\xcc\x23\xd0\xce\xa4\x9c\
\x09\xdf\xdd\x4b\x20\xc0\xbc\x08\xa5\x7a\x2d\x8e\xad\x05\x4d\x95\
\x91\xb7\xa1\x59\x89\xcd\xf7\x8f\x74\xfd\x45\x0d\x69\x8d\x35\x93\
\x69\xe2\xf9\x42\x91\xa5\x17\x40\xb2\x78\x0e\xcc\x1d\x3b\xb6\x6e\
\xe5\xee\x57\x2d\x34\x54\xc4\x1e\x5b\x62\x52\xd3\x70\xd6\xa9\x01\
\x73\x88\x4b\x24\xab\x7b\x79\xc9\x68\x96\x08\x9f\x8b\xdd\x5c\x16\
\xfd\x7c\x7a\xc3\x38\x2f\xc1\x6a\xc1\x4b\xee\x39\x9a\xb5\x80\xd6\
\xf4\xa9\x13\x3a\x6d\x4c\x44\x2d\xc7\xbe\x17\xe5\xa3\x3f\x06\xa5\
\xdd\x72\x41\x2d\x8a\xae\x1a\x8a\x42\xca\xf0\x2f\x4a\x78\x8b\xaa\
\xba\xb2\x26\x44\x5f\xbc\x39\x44\x85\xa6\x48\x76\x8c\xc7\x5b\x30\
\x82\x35\x37\x26\x6c\x71\xfa\x0c\x0b\x2f\x8b\x84\x6a\x1a\x51\x86\
\x16\xe2\xb7\xf2\xa2\xa8\x8e\x54\x3b\x5c\xf9\x60\xee\x5b\xc5\x79\
\xdb\xf4\xbe\xb1\x18\x19\x70\xc0\x1a\x38\xcc\xd4\x70\xe7\x32\xc4\
\x5c\x10\x53\xb9\xe0\x8d\xda\x6a\x40\x84\x9a\x7b\xc3\xcf\xcf\xaf\
\xb6\xfa\x1c\x5b\x0d\xde\xb7\x80\x66\x3e\xe0\x5f\x70\x85\x89\xd8\
\xa9\x94\x07\x22\xdd\x26\x56\xaf\x0e\x9d\x98\x61\x8c\x14\x6c\x30\
\xec\x19\x64\xb0\x95\x6a\x22\x18\xf4\x0c\x4e\x28\xdd\xaa\x2b\xdc\
\x81\x74\x0e\xdc\x1e\x48\x9b\x61\xa3\x68\x71\xca\x60\xf1\x49\xee\
\xf5\xc7\x8c\x73\x01\x63\x91\x64\x52\x96\x08\x99\x8a\x83\x79\x2e\
\xeb\x8c\x28\x4a\xa3\x5b\x9c\xb4\x07\xd5\x6d\x88\x53\x24\xfe\x78\
\x08\x28\x68\x04\x18\x81\x15\xba\x13\x41\x86\xe8\xfc\x1f\x41\x8a\
\x0f\x8f\xb5\x86\x13\x4a\x67\xcd\x05\x35\x56\xc3\x9f\x41\xe0\x0e\
\x46\x23\x49\xc2\x41\x4d\xb4\x64\x00\xc4\xed\x9f\x89\xad\xc9\x9b\
\xa6\x78\x1e\x65\xe0\xf6\xdf\x0a\xa9\x6a\x99\xdb\xd6\x30\xf5\x30\
\xaf\x25\xcc\x7f\x11\x79\xdc\xec\x8c\x30\x5f\x23\x22\x61\x52\xbb\
\x25\x8c\x3d\x16\x24\x69\x6e\xea\xf1\xf0\x7e\x6b\x5f\x69\x60\xeb\
\x73\xf6\x58\xd9\xef\xd8\x39\x13\x6e\x69\xd2\x10\x1f\x4a\x9a\x07\
\x51\xe6\xd1\x08\x53\x08\x32\x9f\x67\x0c\x9e\x8f\x35\xef\xa1\xff\
\x57\xde\x7c\x4a\xde\xbc\xef\x2c\x3e\x8c\x39\x67\x45\xb4\x3d\x2d\
\x7d\xf6\x47\xbd\x0e\xfa\x1c\x9f\x75\xd1\xe7\xbb\xf1\x33\xd1\xe7\
\x16\xab\x57\x0e\xdd\x5d\x78\x8e\x0f\x2b\x3c\x47\xc7\x2b\x3c\xd5\
\xbb\xcf\x33\x92\xe8\xf0\x95\x44\x77\x63\xfd\xd4\x24\xfa\xa6\x73\
\x33\xf6\xa1\xae\xd1\x59\x07\x73\xbd\x19\x74\x31\xd7\xf0\xb9\x98\
\xeb\x4e\xe5\xc2\xcb\xa5\x2d\x53\x68\xe8\xaa\xcc\x7b\xc4\x57\x82\
\xf2\xf0\x7d\xd8\x77\x82\xeb\x8b\x4f\x08\xc7\x09\x65\xfc\xd8\x1f\
\x07\x8e\xf7\x69\x60\xf8\x70\x86\x2e\xd3\x2c\x04\xff\x67\x15\x9f\
\x6d\x8e\x49\xc1\xbc\x0a\x54\x3b\x5a\x5d\x55\x0a\x5e\x88\x02\x25\
\x2f\x54\x94\x3a\x08\xfe\x50\x15\x8b\x20\x2e\x60\xa4\xf8\xea\x22\
\xa1\x4d\x3c\x96\x82\xa4\x76\xf1\xba\x37\x07\x94\xa5\x80\x38\x45\
\xf3\x0c\x47\x41\x3e\x49\x17\x31\x68\xc1\x68\x8c\x7e\x12\xba\x22\
\xea\x39\xbe\x49\x20\x3d\x7d\x7c\x69\xb3\xfb\xdc\x91\x2e\x6c\xfd\
\x2c\x5d\x3c\xa0\x8a\xca\x11\xa8\x59\x9b\x0b\xfc\x5c\x51\x7e\x80\
\x20\x10\xd9\xfc\x9d\x64\x21\x96\x74\xbd\xf0\xa7\x7a\x1d\x2f\x90\
\x2d\x0e\x4f\xa1\xd1\xef\x48\xa1\xc7\x27\xd0\xf5\x8e\x04\x12\xf1\
\xf8\x77\x02\x64\x16\x82\xc8\x97\x9c\x96\xcc\xec\x09\x54\xa5\x54\
\x24\x0d\xa1\x1c\x85\x1e\x09\x22\x31\x3e\xdf\x98\x29\x78\x68\x58\
\xef\xce\xa0\x6f\xa9\xe9\xe8\xe3\x6d\xec\x1d\xe3\x15\x9b\x2f\x30\
\xcc\xf7\x3f\x14\x8d\x7a\xb6\x38\x7e\xcc\x0f\xa9\x0f\x29\x63\xcb\
\x0a\xf6\xbb\xd6\x61\xd4\xaf\xcd\xa3\x70\x8f\xaa\xd5\x2c\x58\x75\
\xad\x3a\x68\xd4\xaa\x45\x99\x3a\x6c\x94\xa9\x46\x85\x5a\x77\xc5\
\xa8\x4b\x4b\x90\x2a\x48\x56\x60\xd4\xbc\x51\xbc\x57\xeb\x8b\x8f\
\x89\x35\xb6\x50\x7e\x83\x31\xb1\xfa\x7d\xcb\x96\x33\x13\xbc\x8e\
\xbd\x64\x91\x11\x5f\x02\xe5\xfe\x3b\x55\xfd\x0b\x71\x48\x7d\xc5\
\x31\xcc\x68\xc6\x7c\xc1\xec\xb5\x59\xf2\x12\x2b\x4b\x39\x8d\x73\
\x8b\xa9\xf2\xa4\x3a\x92\x7b\x59\xb9\xe8\xaa\x14\xc3\xe5\xe5\x96\
\xdc\x8f\x35\x07\x12\xa4\xee\xcd\x34\x4b\xc3\x42\x5e\x0c\x9e\xe4\
\x70\x79\x81\x58\xb6\xd0\x62\xe7\x97\x5f\xe9\x69\x28\x91\x53\xa3\
\x0a\x81\xba\xe1\x6e\x4f\x6a\xa5\x79\xab\x37\x4d\x97\x77\xb9\x24\
\xb5\x1d\xcf\x2d\xcd\xc3\xed\x08\x95\xd2\xc3\x9d\x31\x07\xd4\x45\
\x23\x83\x54\x6d\x76\xaa\xc2\xc2\xa7\x84\x80\xda\x6c\xd9\x77\xec\
\x0c\xbb\x27\xff\x03\x16\x13\x63\x21\
\x00\x00\x07\x4c\
\x00\
\x00\x29\xd1\x78\x9c\xed\x59\x5b\x8f\xe2\x46\x16\x7e\xef\x5f\xe1\
@@ -10089,30 +10050,30 @@ qt_resource_struct = "\
\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x3e\x30\
\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x01\x08\x08\
\x00\x00\x00\x38\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x05\x12\x00\x01\x00\x00\x00\x01\x00\x02\x30\x38\
\x00\x00\x04\x1e\x00\x00\x00\x00\x00\x01\x00\x01\xf2\x69\
\x00\x00\x02\xfc\x00\x00\x00\x00\x00\x01\x00\x01\xa3\xf7\
\x00\x00\x05\xb2\x00\x01\x00\x00\x00\x01\x00\x02\x5b\xca\
\x00\x00\x04\xe4\x00\x01\x00\x00\x00\x01\x00\x02\x29\x66\
\x00\x00\x03\x36\x00\x01\x00\x00\x00\x01\x00\x01\xb2\x66\
\x00\x00\x03\x88\x00\x01\x00\x00\x00\x01\x00\x01\xc5\xed\
\x00\x00\x02\xa0\x00\x01\x00\x00\x00\x01\x00\x01\x89\x57\
\x00\x00\x04\x5e\x00\x00\x00\x00\x00\x01\x00\x02\x0c\x43\
\x00\x00\x02\x7e\x00\x01\x00\x00\x00\x01\x00\x01\x80\x5e\
\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x01\xbb\xbe\
\x00\x00\x02\x34\x00\x01\x00\x00\x00\x01\x00\x01\x6f\xb6\
\x00\x00\x02\x5e\x00\x01\x00\x00\x00\x01\x00\x01\x79\x5e\
\x00\x00\x04\x8e\x00\x01\x00\x00\x00\x01\x00\x02\x1b\xb1\
\x00\x00\x03\xf4\x00\x00\x00\x00\x00\x01\x00\x01\xe1\xe8\
\x00\x00\x04\xbc\x00\x01\x00\x00\x00\x01\x00\x02\x21\x01\
\x00\x00\x05\x3c\x00\x00\x00\x00\x00\x01\x00\x02\x37\x13\
\x00\x00\x03\xac\x00\x01\x00\x00\x00\x01\x00\x01\xcb\x04\
\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x02\x53\x50\
\x00\x00\x05\x66\x00\x01\x00\x00\x00\x01\x00\x02\x49\x16\
\x00\x00\x04\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x06\x2b\
\x00\x00\x02\xd2\x00\x00\x00\x00\x00\x01\x00\x01\x91\x99\
\x00\x00\x03\xd6\x00\x00\x00\x00\x00\x01\x00\x01\xd2\xec\
\x00\x00\x02\x00\x00\x01\x00\x00\x00\x01\x00\x01\x68\x66\
\x00\x00\x05\x12\x00\x01\x00\x00\x00\x01\x00\x02\x2d\xc6\
\x00\x00\x04\x1e\x00\x00\x00\x00\x00\x01\x00\x01\xef\xf7\
\x00\x00\x02\xfc\x00\x00\x00\x00\x00\x01\x00\x01\xa1\x85\
\x00\x00\x05\xb2\x00\x01\x00\x00\x00\x01\x00\x02\x59\x58\
\x00\x00\x04\xe4\x00\x01\x00\x00\x00\x01\x00\x02\x26\xf4\
\x00\x00\x03\x36\x00\x01\x00\x00\x00\x01\x00\x01\xaf\xf4\
\x00\x00\x03\x88\x00\x01\x00\x00\x00\x01\x00\x01\xc3\x7b\
\x00\x00\x02\xa0\x00\x01\x00\x00\x00\x01\x00\x01\x86\xe5\
\x00\x00\x04\x5e\x00\x00\x00\x00\x00\x01\x00\x02\x09\xd1\
\x00\x00\x02\x7e\x00\x01\x00\x00\x00\x01\x00\x01\x7d\xec\
\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x01\xb9\x4c\
\x00\x00\x02\x34\x00\x01\x00\x00\x00\x01\x00\x01\x6d\x44\
\x00\x00\x02\x5e\x00\x01\x00\x00\x00\x01\x00\x01\x76\xec\
\x00\x00\x04\x8e\x00\x01\x00\x00\x00\x01\x00\x02\x19\x3f\
\x00\x00\x03\xf4\x00\x00\x00\x00\x00\x01\x00\x01\xdf\x76\
\x00\x00\x04\xbc\x00\x01\x00\x00\x00\x01\x00\x02\x1e\x8f\
\x00\x00\x05\x3c\x00\x00\x00\x00\x00\x01\x00\x02\x34\xa1\
\x00\x00\x03\xac\x00\x01\x00\x00\x00\x01\x00\x01\xc8\x92\
\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x02\x50\xde\
\x00\x00\x05\x66\x00\x01\x00\x00\x00\x01\x00\x02\x46\xa4\
\x00\x00\x04\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x03\xb9\
\x00\x00\x02\xd2\x00\x00\x00\x00\x00\x01\x00\x01\x8f\x27\
\x00\x00\x03\xd6\x00\x00\x00\x00\x00\x01\x00\x01\xd0\x7a\
\x00\x00\x02\x00\x00\x01\x00\x00\x00\x01\x00\x01\x65\xf4\
\x00\x00\x01\xd8\x00\x01\x00\x00\x00\x01\x00\x01\x61\x46\
"

View File

@@ -164,22 +164,6 @@
<string>IFC import</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For the IFC reader to function, you need an IFC Schema Express file (.exp) available here:&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#508ed8;&quot;&gt;http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
@@ -201,39 +185,6 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>IFC Schema file location</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefFileChooser" name="gui::preffilechooser">
<property name="toolTip">
<string>For the IFC reader to function, you need an IFC Schema Express file (.exp). For licensing reasons we are not allowed to ship that file with FreeCAD, so you must download it yourself. Place that file in some location on your computer, and select the file here.</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>IfcSchema</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Arch</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -259,26 +210,29 @@ p, li { white-space: pre-wrap; }
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
<customwidget>
<class>Gui::FileChooser</class>
<extends>QWidget</extends>
<header>Gui/FileDialog.h</header>
</customwidget>
<customwidget>
<class>Gui::ColorButton</class>
<extends>QPushButton</extends>
<header>Gui/Widgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefFileChooser</class>
<extends>Gui::FileChooser</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefColorButton</class>
<extends>Gui::ColorButton</extends>

View File

@@ -21,7 +21,7 @@
#* *
#***************************************************************************
import ifcReader, FreeCAD, Arch, Draft, os, sys, time, tempfile
import ifcReader, FreeCAD, Arch, Draft, os, sys, time, tempfile, Part
from draftlibs import fcvec
__title__="FreeCAD IFC importer"
@@ -29,6 +29,8 @@ __author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
DEBUG = True
SCHEMA = "http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp"
SKIP = ["IfcOpeningElement"]
pyopen = open # because we'll redefine open below
def open(filename):
@@ -38,9 +40,10 @@ def open(filename):
doc.Label = decode(docname)
FreeCAD.ActiveDocument = doc
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
p = p.GetBool("useIfcOpenShell")
if p:
readOpenShell(filename)
op = p.GetBool("useIfcOpenShell")
ip = p.GetBool("useIfcParser")
if op:
readOpenShell(filename,useParser=ip)
else:
read(filename)
return doc
@@ -59,15 +62,14 @@ def decode(name):
def getSchema():
"retrieves the express schema"
default = "IFC2X3_TC1.exp"
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
p = p.GetString("IfcSchema")
if p:
if os.path.exists(p):
return p
p = os.path.join(FreeCAD.ConfigGet("UserAppData"),default)
p = None
p = os.path.join(FreeCAD.ConfigGet("UserAppData"),SCHEMA.split('/')[-1])
if os.path.exists(p):
return p
import ArchCommands
p = ArchCommands.download(SCHEMA)
if p:
return p
return None
def getIfcOpenShell():
@@ -81,8 +83,12 @@ def getIfcOpenShell():
else:
return True
def readOpenShell(filename):
def readOpenShell(filename,useParser=False):
"Parses an IFC file with IfcOpenShell"
altifc = None
if useParser:
altifc = parseFile(filename)
if getIfcOpenShell():
USESHAPES = False
@@ -97,72 +103,100 @@ def readOpenShell(filename):
meshdata = []
n = obj.name
if not n: n = "Unnamed"
if USESHAPES:
if obj.type in SKIP:
pass
elif altifc and (obj.type == "IfcWallStandardCase"):
if USESHAPES:
makeWall(altifc.Entities[obj.id],shape=getShape(obj))
else:
makeWall(altifc.Entities[obj.id])
elif USESHAPES:
# treat as Parts
import Part
tf = tempfile.mkstemp(suffix=".brp")[1]
of = pyopen(tf,"wb")
of.write(obj.mesh.brep_data)
of.close()
sh = Part.read(tf)
sh = getShape(obj)
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
nobj.Shape = sh
os.remove(tf)
else:
# treat as meshes
import Mesh
f = obj.mesh.faces
v = obj.mesh.verts
for i in range(0, len(f), 3):
face = []
for j in range(3):
vi = f[i+j]*3
face.append([v[vi],v[vi+1],v[vi+2]])
meshdata.append(face)
newmesh = Mesh.Mesh(meshdata)
me,pl = getMesh(obj)
nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n)
nobj.Mesh = newmesh
# apply transformation matrix
m = obj.matrix
mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9],
m[1], m[4], m[7], m[10],
m[2], m[5], m[8], m[11],
0, 0, 0, 1)
nobj.Placement = FreeCAD.Placement(mat)
nobj.Mesh = me
nobj.Placement = pl
if not IfcImport.Next():
break
IfcImport.CleanUp()
return None
def getMesh(obj):
"gets mesh and placement from an IfcOpenShell object"
import Mesh
f = obj.mesh.faces
v = obj.mesh.verts
for i in range(0, len(f), 3):
face = []
for j in range(3):
vi = f[i+j]*3
face.append([v[vi],v[vi+1],v[vi+2]])
meshdata.append(face)
me = Mesh.Mesh(meshdata)
# get transformation matrix
m = obj.matrix
mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9],
m[1], m[4], m[7], m[10],
m[2], m[5], m[8], m[11],
0, 0, 0, 1)
pl = FreeCAD.Placement(mat)
return me,pl
def getShape(obj):
"gets a shape from an IfcOpenShell object"
tf = tempfile.mkstemp(suffix=".brp")[1]
of = pyopen(tf,"wb")
of.write(obj.mesh.brep_data)
of.close()
sh = Part.read(tf)
os.remove(tf)
m = obj.matrix
mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9],
m[1], m[4], m[7], m[10],
m[2], m[5], m[8], m[11],
0, 0, 0, 1)
sh.Placement = FreeCAD.Placement(mat)
return sh
def read(filename):
"processes an ifc file and add its objects to the given document"
t1 = time.time()
ifc = parseFile(filename)
t2 = time.time()
if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1))
# getting walls
for w in ifc.getEnt("IFCWALLSTANDARDCASE"):
makeWall(w)
# getting floors
for f in ifc.getEnt("IFCBUILDINGSTOREY"):
makeCell(f,"Floor")
# getting buildings
for b in ifc.getEnt("IFCBUILDING"):
makeCell(b,"Building")
FreeCAD.ActiveDocument.recompute()
t3 = time.time()
if DEBUG: print "done processing",ifc,"in %s s" % ((t3-t1))
def parseFile(filename):
"parses an IFC file"
schema=getSchema()
if schema:
if DEBUG: global ifc
if DEBUG: print "opening",filename,"..."
ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG)
t2 = time.time()
if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1))
# getting walls
for w in ifc.getEnt("IFCWALLSTANDARDCASE"):
makeWall(w)
# getting floors
for f in ifc.getEnt("IFCBUILDINGSTOREY"):
makeCell(f,"Floor")
# getting buildings
for b in ifc.getEnt("IFCBUILDING"):
makeCell(b,"Building")
FreeCAD.ActiveDocument.recompute()
t3 = time.time()
if DEBUG: print "done processing",ifc,"in %s s" % ((t3-t1))
return ifc
else:
FreeCAD.Console.PrintWarning("IFC Schema not found, IFC import disabled. See Arch Preferences to get a schema")
FreeCAD.Console.PrintWarning("IFC Schema not found, IFC import disabled.\n")
return None
def makeCell(entity,mode="Cell"):
"makes a cell in the freecad document"
@@ -202,10 +236,16 @@ def makeCell(entity,mode="Cell"):
except:
if DEBUG: print "error: skipping cell",entity.id
def makeWall(entity):
def makeWall(entity,shape=None):
"makes a wall in the freecad document"
try:
if DEBUG: print "=====> making wall",entity.id
if shape:
sh = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody")
sh.Shape = shape
wall = Arch.makeWall(sh)
if DEBUG: print "made wall object ",entity.id,":",wall
return
placement = wall = wire = body = width = height = None
placement = getPlacement(entity.ObjectPlacement)
if DEBUG: print "got wall placement",entity.id,":",placement

View File

@@ -44,3 +44,5 @@ if(FREECAD_BUILD_SANDBOX)
add_subdirectory(Sandbox)
endif(FREECAD_BUILD_SANDBOX)
add_subdirectory(Surfaces)
add_subdirectory(Ship)

View File

@@ -970,6 +970,7 @@ def draftify(objectslist,makeblock=False):
wire. If makeblock is True, multiple objects will be grouped in a block'''
from draftlibs import fcgeo
import Part
if not isinstance(objectslist,list):
objectslist = [objectslist]
newobjlist = []

View File

@@ -154,6 +154,7 @@ class DraftToolBar:
def __init__(self):
self.tray = None
self.sourceCmd = None
self.cancel = None
self.taskmode = Draft.getParam("UiMode")
self.paramcolor = Draft.getParam("color")>>8
self.color = QtGui.QColor(self.paramcolor)
@@ -465,14 +466,14 @@ class DraftToolBar:
def taskUi(self,title):
if self.taskmode:
self.isTaskOn = True
FreeCADGui.Control.closeDialog()
todo.delay(FreeCADGui.Control.closeDialog,None)
self.baseWidget = QtGui.QWidget()
self.setTitle(title)
self.layout = QtGui.QVBoxLayout(self.baseWidget)
self.setupToolBar(task=True)
self.retranslateUi(self.baseWidget)
self.panel = DraftTaskPanel(self.baseWidget)
FreeCADGui.Control.showDialog(self.panel)
todo.delay(FreeCADGui.Control.showDialog,self.panel)
else:
self.setTitle(title)
@@ -509,7 +510,8 @@ class DraftToolBar:
self.labelx.setText(translate("draft", "Center X"))
self.continueCmd.show()
def pointUi(self,title=translate("draft","Point")):
def pointUi(self,title=translate("draft","Point"),cancel=None):
if cancel: self.cancel = cancel
self.taskUi(title)
self.xValue.setEnabled(True)
self.yValue.setEnabled(True)
@@ -832,7 +834,11 @@ class DraftToolBar:
def finish(self):
"finish button action"
self.sourceCmd.finish(False)
if self.sourceCmd:
self.sourceCmd.finish(False)
if self.cancel:
self.cancel()
self.cancel = None
def closeLine(self):
"close button action"

View File

@@ -430,13 +430,16 @@ class Snapper:
# get the intersection points
pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True)
if pt:
return [pt[0],'ortho',pt[0]]
return [pt[0],'ortho',pt[0]]
if eline:
tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape()
# get the intersection points
pt = fcgeo.findIntersection(eline,tmpEdge2,True,True)
if pt:
try:
tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape()
# get the intersection points
pt = fcgeo.findIntersection(eline,tmpEdge2,True,True)
if pt:
return [pt[0],'ortho',pt[0]]
except:
return None
return None
def snapToElines(self,e1,e2):
@@ -613,15 +616,23 @@ class Snapper:
if self.constrainLine:
self.constrainLine.off()
def getPoint(self,last=None,callback=None):
"""getPoint([last],[callback]) : gets a 3D point from the screen. You can provide an existing point,
in that case additional snap options and a tracker are available. You can also passa function as
callback, which will get called with the resulting point as argument, when a point is clicked:
def getPoint(self,last=None,callback=None,movecallback=None):
"""getPoint([last],[callback],[movecallback]) : gets a 3D point from the screen. You
can provide an existing point, in that case additional snap options and a tracker
are available. You can also pass a function as callback, which will get called
with the resulting point as argument, when a point is clicked, and optionally
another callback which gets called when the mouse is moved.
If the operation gets cancelled (the user pressed Escape), no point is returned.
Example:
def cb(point):
print "got a 3D point: ",point
FreeCADGui.Snapper.getPoint(callback=cb)
"""
if point:
print "got a 3D point: ",point
FreeCADGui.Snapper.getPoint(callback=cb)"""
self.pt = None
self.ui = FreeCADGui.draftToolBar
self.view = FreeCADGui.ActiveDocument.ActiveView
@@ -642,6 +653,8 @@ class Snapper:
self.ui.displayPoint(self.pt,last,plane=FreeCAD.DraftWorkingPlane,mask=FreeCADGui.Snapper.affinity)
if self.trackLine:
self.trackLine.p2(self.pt)
if movecallback:
movecallback(self.pt)
def click(event_cb):
event = event_cb.getEvent()
@@ -656,10 +669,21 @@ class Snapper:
callback(self.pt)
self.pt = None
def cancel():
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
FreeCADGui.Snapper.off()
self.ui.offUi()
if self.trackLine:
self.trackLine.off()
if callback:
callback(None)
# adding 2 callback functions
self.ui.pointUi()
self.ui.pointUi(cancel=cancel)
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click)
self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)
if not hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper = Snapper()

View File

@@ -623,3 +623,66 @@ class gridTracker(Tracker):
rot = FreeCAD.Rotation()
rot.Q = self.trans.rotation.getValue().getValue()
return rot.multVec(Vector(pu,pv,0))
class boxTracker(Tracker):
"A box tracker, can be based on a line object"
def __init__(self,line=None,width=0.1,height=1):
self.trans = coin.SoTransform()
m = coin.SoMaterial()
m.transparency.setValue(0.8)
m.diffuseColor.setValue([0.4,0.4,0.6])
self.cube = coin.SoCube()
self.cube.height.setValue(width)
self.cube.depth.setValue(height)
self.baseline = None
if line:
self.baseline = line
self.update()
Tracker.__init__(self,children=[self.trans,m,self.cube])
def update(self,line=None,normal=None):
import WorkingPlane
from draftlibs import fcgeo
if not normal:
normal = FreeCAD.DraftWorkingPlane.axis
if line:
if isinstance(line,list):
bp = line[0]
lvec = line[1].sub(line[0])
else:
lvec = fcgeo.vec(line.Shape.Edges[0])
bp = line.Shape.Edges[0].Vertexes[0].Point
elif self.baseline:
lvec = fcgeo.vec(self.baseline.Shape.Edges[0])
bp = self.baseline.Shape.Edges[0].Vertexes[0].Point
else:
return
right = lvec.cross(normal)
self.cube.width.setValue(lvec.Length)
p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)])
self.trans.rotation.setValue(p.Rotation.Q)
bp = bp.add(fcvec.scale(lvec,0.5))
bp = bp.add(fcvec.scaleTo(normal,self.cube.depth.getValue()/2))
self.pos(bp)
def pos(self,p):
self.trans.translation.setValue(fcvec.tup(p))
def width(self,w=None):
if w:
self.cube.height.setValue(w)
else:
return self.cube.height.getValue()
def length(self,l=None):
if l:
self.cube.width.setValue(l)
else:
return self.cube.width.getValue()
def heigth(self,h=None):
if h:
self.cube.depth.setValue(h)
self.update()
else:
return self.cube.depth.getValue()

View File

@@ -1,5 +1,5 @@
#SUBDIRS=Part Mesh Points Raytracing Image Drawing Complete Draft Test TemplatePyMod
SUBDIRS=Points Complete Draft Test TemplatePyMod Web Start Idf Arch
SUBDIRS=Points Complete Draft Test TemplatePyMod Web Start Idf Arch Surfaces Ship
#if HAVE_OPENCV
SUBDIRS += Image

124
src/Mod/Ship/CMakeLists.txt Normal file
View File

@@ -0,0 +1,124 @@
SET(ShipMain_SRCS
InitGui.py
ShipGui.py
Instance.py
)
SOURCE_GROUP("" FILES ${ShipMain_SRCS})
SET(ShipIcons_SRCS
Icons/AreaCurveIco.png
Icons/AreaCurveIco.xcf
Icons/AreaCurveIco.xpm
Icons/DataIco.png
Icons/DataIco.xcf
Icons/DataIco.xpm
Icons/DiscretizeIco.png
Icons/DiscretizeIco.xcf
Icons/DiscretizeIco.xpm
Icons/HydrostaticsIco.png
Icons/HydrostaticsIco.xcf
Icons/HydrostaticsIco.xpm
Icons/Ico.png
Icons/Ico.xcf
Icons/Ico.xpm
Icons/OutlineDrawIco.png
Icons/OutlineDrawIco.xcf
Icons/OutlineDrawIco.xpm
Icons/ReparametrizeIco.png
Icons/ReparametrizeIco.xcf
Icons/ReparametrizeIco.xpm
Icons/Ship.xcf
Icons/Ship.xpm
)
SOURCE_GROUP("shipicons" FILES ${ShipIcons_SRCS})
SET(ShipCreateShip_SRCS
shipCreateShip/__init__.py
shipCreateShip/Preview.py
shipCreateShip/TaskPanel.py
shipCreateShip/TaskPanel.ui
)
SOURCE_GROUP("shipcreateship" FILES ${ShipCreateShip_SRCS})
SET(ShipOutlineDraw_SRCS
shipOutlineDraw/__init__.py
shipOutlineDraw/Plot.py
shipOutlineDraw/Preview.py
shipOutlineDraw/TaskPanel.py
shipOutlineDraw/TaskPanel.ui
)
SOURCE_GROUP("shipoutlinedraw" FILES ${ShipOutlineDraw_SRCS})
SET(ShipAreasCurve_SRCS
shipAreasCurve/__init__.py
shipAreasCurve/Preview.py
shipAreasCurve/TaskPanel.py
shipAreasCurve/TaskPanel.ui
)
SOURCE_GROUP("shipareascurve" FILES ${ShipAreasCurve_SRCS})
SET(ShipHydrostatics_SRCS
shipHydrostatics/__init__.py
shipHydrostatics/Tools.py
)
SOURCE_GROUP("shiphydrostatics" FILES ${ShipHydrostatics_SRCS})
SET(ShipUtils_SRCS
shipUtils/__init__.py
shipUtils/Math.py
shipUtils/Paths.py
shipUtils/Translator.py
)
SOURCE_GROUP("shiputils" FILES ${ShipUtils_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS})
ADD_CUSTOM_TARGET(Ship ALL
SOURCES ${all_files}
)
fc_copy_sources("Mod/Ship" "Ship" ${all_files})
INSTALL(
FILES
${ShipIcons_SRCS}
DESTINATION
Mod/Ship/Icons
)
INSTALL(
FILES
${ShipCreateShip_SRCS}
DESTINATION
Mod/Ship/shipCreateShip
)
INSTALL(
FILES
${ShipOutlineDraw_SRCS}
DESTINATION
Mod/Ship/shipOutlineDraw
)
INSTALL(
FILES
${ShipAreasCurve_SRCS}
DESTINATION
Mod/Ship/shipAreasCurve
)
INSTALL(
FILES
${ShipHydrostatics_SRCS}
DESTINATION
Mod/Ship/shipHydrostatics
)
INSTALL(
FILES
${ShipUtils_SRCS}
DESTINATION
Mod/Ship/shipUtils
)
INSTALL(
FILES
${ShipMain_SRCS}
DESTINATION
Mod/Ship
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

View File

@@ -0,0 +1,841 @@
/* XPM */
static char * AreaCurveIco_xpm[] = {
"128 128 710 2",
" c None",
". c #B1B1B1",
"+ c #000001",
"@ c #000000",
"# c #010101",
"$ c #020202",
"% c #B0B0B0",
"& c #030303",
"* c #B1B1B0",
"= c #AFAFAF",
"- c #040404",
"; c #AFB0B0",
"> c #B0AFAF",
", c #B0AFB0",
"' c #AEAFAE",
") c #050505",
"! c #AFAEAE",
"~ c #AEAEAE",
"{ c #060606",
"] c #ADACAC",
"^ c #070707",
"/ c #070706",
"( c #ADADAD",
"_ c #ACACAC",
": c #080708",
"< c #ACADAD",
"[ c #ACABAB",
"} c #090909",
"| c #AAABAA",
"1 c #09090A",
"2 c #090A0A",
"3 c #AAABAB",
"4 c #A9A9AA",
"5 c #0A0A0A",
"6 c #0B0A0B",
"7 c #AAAAAA",
"8 c #A9A9A9",
"9 c #0C0C0B",
"0 c #0C0B0B",
"a c #A8A8A8",
"b c #0C0D0D",
"c c #0D0D0C",
"d c #A7A8A7",
"e c #0E0E0D",
"f c #0D0D0E",
"g c #A7A8A8",
"h c #A6A6A7",
"i c #0E0F0F",
"j c #A6A6A5",
"k c #100F0F",
"l c #0F0F0F",
"m c #A6A6A6",
"n c #A5A5A5",
"o c #111010",
"p c #111110",
"q c #A6A5A5",
"r c #A4A4A4",
"s c #111111",
"t c #A4A5A4",
"u c #A3A3A3",
"v c #131212",
"w c #A2A3A3",
"x c #131314",
"y c #131313",
"z c #A3A2A3",
"A c #A2A2A2",
"B c #141414",
"C c #A1A1A1",
"D c #151515",
"E c #A1A1A2",
"F c #A0A0A0",
"G c #161616",
"H c #A1A0A0",
"I c #9F9F9F",
"J c #181617",
"K c #171717",
"L c #181818",
"M c #9E9E9D",
"N c #191919",
"O c #191819",
"P c #9E9E9E",
"Q c #9D9D9D",
"R c #1A191A",
"S c #1A1A1A",
"T c #9D9C9C",
"U c #1B1B1A",
"V c #1B1B1B",
"W c #9C9C9C",
"X c #9B9C9B",
"Y c #1C1C1C",
"Z c #9B9B9B",
"` c #9A9A9A",
" . c #1C1D1D",
".. c #1D1C1D",
"+. c #9A9B9B",
"@. c #1D1D1D",
"#. c #1E1D1E",
"$. c #989998",
"%. c #1F1E1F",
"&. c #1E1E1F",
"*. c #999999",
"=. c #989898",
"-. c #201F1F",
";. c #20201F",
">. c #999898",
",. c #101010",
"'. c #3B3B3B",
"). c #404040",
"!. c #403F40",
"~. c #3F403F",
"{. c #282828",
"]. c #989797",
"^. c #212121",
"/. c #212020",
"(. c #979797",
"_. c #696969",
":. c #C2C1C1",
"<. c #EFF0EF",
"[. c #F0F0F0",
"}. c #F0EFEF",
"|. c #F0F0EF",
"1. c #EFEFEF",
"2. c #EEEFEF",
"3. c #E2E2E2",
"4. c #A09FA0",
"5. c #585858",
"6. c #969696",
"7. c #212122",
"8. c #212221",
"9. c #969797",
"0. c #121212",
"a. c #939292",
"b. c #ECECEC",
"c. c #F1F0F1",
"d. c #EEEEEE",
"e. c #EEEDEE",
"f. c #EEEDED",
"g. c #E5E5E5",
"h. c #8D8D8D",
"i. c #959695",
"j. c #222323",
"k. c #222322",
"l. c #2F2F2F",
"m. c #D6D6D6",
"n. c #F1F1F0",
"o. c #F1F0F0",
"p. c #EFF0F0",
"q. c #EDEEED",
"r. c #EDEDED",
"s. c #ECEDED",
"t. c #ECEDEC",
"u. c #D8D8D8",
"v. c #4D4D4D",
"w. c #959595",
"x. c #242323",
"y. c #242324",
"z. c #585859",
"A. c #E8E8E8",
"B. c #F0F1F1",
"C. c #EEEEEF",
"D. c #EDEEEE",
"E. c #EDEDEC",
"F. c #EBEBEC",
"G. c #EBEBEB",
"H. c #949494",
"I. c #252424",
"J. c #606060",
"K. c #F1F1F1",
"L. c #F0F0F1",
"M. c #EFEEEE",
"N. c #EDEDEE",
"O. c #EDECED",
"P. c #ECECED",
"Q. c #ECEBEB",
"R. c #ECEBEC",
"S. c #EBECEB",
"T. c #EAEBEA",
"U. c #D4D4D4",
"V. c #323232",
"W. c #949393",
"X. c #262525",
"Y. c #252525",
"Z. c #949493",
"`. c #3D3D3D",
" + c #EBEBEA",
".+ c #EAEAEA",
"++ c #EAEAE9",
"@+ c #D7D7D7",
"#+ c #292929",
"$+ c #939392",
"%+ c #272626",
"&+ c #262626",
"*+ c #939393",
"=+ c #D9D9D9",
"-+ c #EEEEED",
";+ c #EDECEC",
">+ c #EBEAEB",
",+ c #E9E9E9",
"'+ c #D2D2D1",
")+ c #222222",
"!+ c #929292",
"~+ c #272727",
"{+ c #282727",
"]+ c #F0F1F0",
"^+ c #E9E8E9",
"/+ c #E8E9E8",
"(+ c #C2C1C2",
"_+ c #919191",
":+ c #919291",
"<+ c #606061",
"[+ c #EFEFF0",
"}+ c #EFEEEF",
"|+ c #EFEFEE",
"1+ c #EAEBEB",
"2+ c #EBEAEA",
"3+ c #E9EAE9",
"4+ c #EAE9E9",
"5+ c #E8E9E9",
"6+ c #E8E7E7",
"7+ c #E7E8E8",
"8+ c #8F8F8F",
"9+ c #909090",
"0+ c #2A2929",
"a+ c #919090",
"b+ c #0C0C0C",
"c+ c #DBDBDB",
"d+ c #E9E9EA",
"e+ c #E9E8E8",
"f+ c #E7E7E7",
"g+ c #E7E6E6",
"h+ c #474747",
"i+ c #2B2A2A",
"j+ c #747475",
"k+ c #F0EFF0",
"l+ c #E9E9E8",
"m+ c #E8E8E9",
"n+ c #E7E6E7",
"o+ c #E6E6E6",
"p+ c #D3D3D3",
"q+ c #8F8E8E",
"r+ c #2B2B2B",
"s+ c #E4E4E4",
"t+ c #E9EAEA",
"u+ c #E7E7E8",
"v+ c #E5E5E6",
"w+ c #8D8E8E",
"x+ c #2D2C2C",
"y+ c #2C2C2C",
"z+ c #8E8E8E",
"A+ c #7F807F",
"B+ c #E6E7E7",
"C+ c #E7E7E6",
"D+ c #E6E7E6",
"E+ c #E5E6E5",
"F+ c #E6E6E5",
"G+ c #E4E5E4",
"H+ c #6D6D6D",
"I+ c #8D8C8D",
"J+ c #2D2C2D",
"K+ c #2D2D2D",
"L+ c #E8E8E7",
"M+ c #E6E5E5",
"N+ c #E5E4E4",
"O+ c #DDDEDE",
"P+ c #8C8C8C",
"Q+ c #2F2E2E",
"R+ c #2E2D2E",
"S+ c #8D8C8C",
"T+ c #757575",
"U+ c #EAEAEB",
"V+ c #E8E7E8",
"W+ c #E6E6E7",
"X+ c #E5E5E4",
"Y+ c #E3E4E4",
"Z+ c #E3E3E4",
"`+ c #8C8B8B",
" @ c #8B8B8B",
".@ c #D1D1D1",
"+@ c #E4E3E4",
"@@ c #E3E3E3",
"#@ c #E3E2E3",
"$@ c #444444",
"%@ c #8B8B8A",
"&@ c #312F30",
"*@ c #30302F",
"=@ c #373737",
"-@ c #ECECEB",
";@ c #E5E6E6",
">@ c #E6E5E6",
",@ c #E5E4E5",
"'@ c #E4E3E3",
")@ c #BFBFBE",
"!@ c #8A8A8A",
"~@ c #313130",
"{@ c #E7E8E7",
"]@ c #E1E1E1",
"^@ c #555555",
"/@ c #898989",
"(@ c #898A89",
"_@ c #D9DAD9",
":@ c #E4E4E5",
"<@ c #E3E4E3",
"[@ c #E3E3E2",
"}@ c #E1E1E2",
"|@ c #C2C3C2",
"1@ c #888888",
"2@ c #333232",
"3@ c #333332",
"4@ c #353435",
"5@ c #EBECEC",
"6@ c #E4E4E3",
"7@ c #E3E2E2",
"8@ c #E1E0E0",
"9@ c #E0E0E0",
"0@ c #545454",
"a@ c #878788",
"b@ c #343434",
"c@ c #343334",
"d@ c #7C7C7C",
"e@ c #E2E3E2",
"f@ c #E2E2E3",
"g@ c #E2E1E2",
"h@ c #E2E1E1",
"i@ c #E1E0E1",
"j@ c #E0E1E1",
"k@ c #E0E1E0",
"l@ c #C1C1C0",
"m@ c #868786",
"n@ c #353535",
"o@ c #878687",
"p@ c #C1C1C1",
"q@ c #E2E2E1",
"r@ c #E1E2E1",
"s@ c #E1E1E0",
"t@ c #DFE0E0",
"u@ c #DFDFE0",
"v@ c #DFDFDF",
"w@ c #4A4A4A",
"x@ c #858686",
"y@ c #353635",
"z@ c #363535",
"A@ c #868686",
"B@ c #EAE9EA",
"C@ c #E2E3E3",
"D@ c #E1E2E2",
"E@ c #DFDEDF",
"F@ c #B4B4B4",
"G@ c #858585",
"H@ c #373636",
"I@ c #363736",
"J@ c #858586",
"K@ c #646464",
"L@ c #DFE0DF",
"M@ c #DEDFDF",
"N@ c #DFDFDE",
"O@ c #DEDEDE",
"P@ c #454545",
"Q@ c #848484",
"R@ c #383838",
"S@ c #858485",
"T@ c #DEDEDF",
"U@ c #DDDDDE",
"V@ c #DDDEDD",
"W@ c #B2B2B2",
"X@ c #838483",
"Y@ c #383938",
"Z@ c #393839",
"`@ c #848384",
" # c #0B0B0B",
".# c #E4E5E5",
"+# c #E0DFDF",
"@# c #DEDEDD",
"## c #DDDDDD",
"$# c #DCDCDC",
"%# c #828282",
"&# c #3A393A",
"*# c #3A3939",
"=# c #838283",
"-# c #464646",
";# c #DDDDDC",
"># c #3B3B3A",
",# c #3A3B3B",
"'# c #818181",
")# c #E0E0E1",
"!# c #DFDEDE",
"~# c #DEDDDD",
"{# c #DDDCDD",
"]# c #DCDDDC",
"^# c #DADADB",
"/# c #202020",
"(# c #3C3B3B",
"_# c #828181",
":# c #BCBCBC",
"<# c #E0DFE0",
"[# c #DEDFDE",
"}# c #DCDCDD",
"|# c #DBDCDC",
"1# c #DBDCDB",
"2# c #7A7A7A",
"3# c #808080",
"4# c #3C3C3C",
"5# c #3C3C3D",
"6# c #808180",
"7# c #DEDDDE",
"8# c #DBDBDC",
"9# c #DADBDB",
"0# c #CCCCCC",
"a# c #7F8080",
"b# c #3E3D3D",
"c# c #807F80",
"d# c #424241",
"e# c #DCDDDD",
"f# c #DDDCDC",
"g# c #DADADA",
"h# c #DADBDA",
"i# c #575757",
"j# c #7E7E7E",
"k# c #3F3E3E",
"l# c #3E3E3D",
"m# c #7F7F7F",
"n# c #DCDCDB",
"o# c #DBDBDA",
"p# c #DADAD9",
"q# c #B5B5B5",
"r# c #7E7D7E",
"s# c #3F3F3F",
"t# c #D9D9DA",
"u# c #D8D8D9",
"v# c #7D7D7D",
"w# c #414040",
"x# c #7D7D7E",
"y# c #DAD9DA",
"z# c #D8D9D9",
"A# c #D9D8D8",
"B# c #D9D8D9",
"C# c #7D7C7D",
"D# c #414141",
"E# c #3E3D3E",
"F# c #DAD9D9",
"G# c #D8D9D8",
"H# c #D8D7D8",
"I# c #D2D2D2",
"J# c #7B7C7B",
"K# c #424142",
"L# c #424242",
"M# c #7B7C7C",
"N# c #767676",
"O# c #D7D8D8",
"P# c #686968",
"Q# c #7A7B7B",
"R# c #444243",
"S# c #444342",
"T# c #AEADAD",
"U# c #DBDADA",
"V# c #D8D7D7",
"W# c #D6D7D6",
"X# c #C1C0C0",
"Y# c #454344",
"Z# c #E0E0DF",
"`# c #D6D7D7",
" $ c #797979",
".$ c #464545",
"+$ c #454544",
"@$ c #7A7979",
"#$ c #D9DADA",
"$$ c #D7D8D7",
"%$ c #D7D7D8",
"&$ c #D6D6D7",
"*$ c #D5D5D6",
"=$ c #787878",
"-$ c #474546",
";$ c #787879",
">$ c #6C6C6C",
",$ c #D7D7D6",
"'$ c #D5D5D5",
")$ c #777878",
"!$ c #474646",
"~$ c #DCDBDB",
"{$ c #D9D9D8",
"]$ c #D7D6D7",
"^$ c #D6D6D5",
"/$ c #D5D4D5",
"($ c #737373",
"_$ c #777777",
":$ c #484748",
"<$ c #494748",
"[$ c #D5D6D5",
"}$ c #D4D4D5",
"|$ c #C4C4C4",
"1$ c #494948",
"2$ c #494848",
"3$ c #2A2A2A",
"4$ c #D5D5D4",
"5$ c #D4D5D4",
"6$ c #D3D4D4",
"7$ c #D3D4D3",
"8$ c #494949",
"9$ c #4A4949",
"0$ c #4A494A",
"a$ c #767575",
"b$ c #636263",
"c$ c #D7D6D6",
"d$ c #D6D5D6",
"e$ c #D4D4D3",
"f$ c #747575",
"g$ c #4B4A4B",
"h$ c #4B4B4B",
"i$ c #D5D6D6",
"j$ c #D4D5D5",
"k$ c #D3D2D2",
"l$ c #747473",
"m$ c #4C4B4B",
"n$ c #4C4B4C",
"o$ c #747374",
"p$ c #D1D1D2",
"q$ c #878787",
"r$ c #727273",
"s$ c #4D4C4D",
"t$ c #4D4C4C",
"u$ c #434343",
"v$ c #D8D8D7",
"w$ c #D4D3D4",
"x$ c #D2D3D2",
"y$ c #D2D1D2",
"z$ c #171716",
"A$ c #717272",
"B$ c #4E4D4D",
"C$ c #727272",
"D$ c #D3D3D4",
"E$ c #D1D1D0",
"F$ c #D0D1D1",
"G$ c #676767",
"H$ c #717171",
"I$ c #4F4E4E",
"J$ c #4E4E4E",
"K$ c #727172",
"L$ c #C6C6C6",
"M$ c #D5D4D4",
"N$ c #D3D2D3",
"O$ c #D2D2D3",
"P$ c #D1D2D2",
"Q$ c #D0D0D0",
"R$ c #707071",
"S$ c #504F4F",
"T$ c #504F50",
"U$ c #707070",
"V$ c #D2D3D3",
"W$ c #D2D1D1",
"X$ c #D1D0D0",
"Y$ c #D0CFD0",
"Z$ c #CFCFCF",
"`$ c #505151",
" % c #706F6F",
".% c #515050",
"+% c #6F6F70",
"@% c #616161",
"#% c #D6D5D5",
"$% c #D3D3D2",
"%% c #D1D0D1",
"&% c #D0D0D1",
"*% c #CFD0D0",
"=% c #ABABAB",
"-% c #6F6F6E",
";% c #525151",
">% c #515151",
",% c #6F6F6F",
"'% c #A1A1A0",
")% c #DCDBDC",
"!% c #D4D3D3",
"~% c #CFCFD0",
"{% c #D0D0CF",
"]% c #CECFCF",
"^% c #CECECE",
"/% c #6E6E6E",
"(% c #525252",
"_% c #535252",
":% c #CFCECE",
"<% c #CDCECE",
"[% c #535353",
"}% c #6D6E6D",
"|% c #595858",
"1% c #D0CFCF",
"2% c #CFCECF",
"3% c #CECECF",
"4% c #CECDCD",
"5% c #CDCDCD",
"6% c #CDCCCC",
"7% c #555454",
"8% c #6C6C6D",
"9% c #D1D2D1",
"0% c #CDCDCE",
"a% c #6B6B6B",
"b% c #565455",
"c% c #565555",
"d% c #6B6C6C",
"e% c #CFCFCE",
"f% c #CECFCE",
"g% c #CECECD",
"h% c #CDCCCD",
"i% c #CCCCCD",
"j% c #CBCBCB",
"k% c #303030",
"l% c #6B6A6A",
"m% c #565656",
"n% c #575656",
"o% c #D0D1D0",
"p% c #CFD0CF",
"q% c #CDCECD",
"r% c #CCCCCB",
"s% c #CBCCCB",
"t% c #A9A8A9",
"u% c #6A696A",
"v% c #575756",
"w% c #6A6A6A",
"x% c #CECDCE",
"y% c #CCCBCC",
"z% c #CBCBCC",
"A% c #CACBCA",
"B% c #CBCACA",
"C% c #585758",
"D% c #767576",
"E% c #DBDADB",
"F% c #CDCDCC",
"G% c #CACACA",
"H% c #B9BABA",
"I% c #0D0D0D",
"J% c #686868",
"K% c #595959",
"L% c #595958",
"M% c #686869",
"N% c #CBCCCC",
"O% c #CBCBCA",
"P% c #C9CAC9",
"Q% c #C9C9CA",
"R% c #737372",
"S% c #5B5A59",
"T% c #5B5A5A",
"U% c #686767",
"V% c #CCCDCC",
"W% c #CBCACB",
"X% c #CAC9C9",
"Y% c #C9C9C9",
"Z% c #C6C5C5",
"`% c #666767",
" & c #5B5B5A",
".& c #5B5B5B",
"+& c #1E1E1E",
"@& c #CCCBCB",
"#& c #C8C8C9",
"$& c #C8C8C8",
"%& c #656566",
"&& c #5C5C5C",
"*& c #5C5B5C",
"=& c #666766",
"-& c #B4B3B3",
";& c #C9CACA",
">& c #C9C9C8",
",& c #C7C8C7",
"'& c #C8C7C7",
")& c #656565",
"!& c #5D5C5D",
"~& c #5D5D5C",
"{& c #656665",
"]& c #707171",
"^& c #CCCDCD",
"/& c #C9C8C8",
"(& c #C7C7C8",
"_& c #C8C7C8",
":& c #C7C7C7",
"<& c #C4C4C5",
"[& c #5E5D5D",
"}& c #656464",
"|& c #3E3E3E",
"1& c #CACBCB",
"2& c #CAC9CA",
"3& c #B4B4B3",
"4& c #646363",
"5& c #5F5E5F",
"6& c #5F5E5E",
"7& c #636364",
"8& c #3E3F3F",
"9& c #C9C8C9",
"0& c #C7C8C8",
"a& c #C6C5C6",
"b& c #C5C6C5",
"c& c #BDBDBD",
"d& c #3B3C3C",
"e& c #636363",
"f& c #605F60",
"g& c #605F5F",
"h& c #5A5A5A",
"i& c #C6C6C7",
"j& c #C5C5C5",
"k& c #5D5D5D",
"l& c #5E5E5E",
"m& c #5F5F5E",
"n& c #626261",
"o& c #5C5D5C",
"p& c #666666",
"q& c #666565",
"r& c #656465",
"s& c #636262",
"t& c #626161",
"u& c #616060",
"v& c #616160",
"w& c #5C5D5D",
"x& c #5F5F5F",
"y& c #5F6060",
"z& c #606160",
"A& c #626262",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . . ",
" . . ",
" . . . . ",
" . + @ . ",
" . . # # . . ",
" . $ $ $ $ . ",
" % % & & & & * * ",
" = = = - - ; > , ",
" ' ) ) ! ",
" ~ { { ~ ",
" ] ^ / ( ",
" _ : ^ < ",
" [ } } _ ",
" | 1 2 3 ",
" 4 5 6 7 ",
" 8 9 0 4 ",
" a b c a ",
" d e f g ",
" h i i h ",
" j k l m ",
" n o p q ",
" r s s t ",
" u v v u ",
" w x y z ",
" A B B A ",
" C D D E ",
" F G G H ",
" I J K F ",
" I L L I ",
" M N O P ",
" Q R S Q ",
" T U V W ",
" X Y Y Z ",
" ` ...+. ",
" ` @.#.` ",
" $.%.&.*. ",
" =.-.;.>. @ ,.'.).!.~.{.- @ ",
" ].^./.(. @ D _.:.<.[.}.|.1.2.3.4.5.s @ ",
" 6.7.8.9. 0.a.b.c.[.[.[.1.1.2.d.d.e.f.g.h.B @ ",
" i.j.k.6. @ l.m.n.o.[.}.p.<.1.d.d.e.q.r.s.t.b.u.v.@ ",
" w.x.y.i. @ z.A.n.B.[.[.1.1.C.2.d.d.D.r.E.b.b.b.F.G.Z y ",
" H.I.I.H. @ J.K.K.L.|.1.1.1.C.M.D.q.N.r.O.P.Q.R.S.G.G.T.U.V. ",
" W.X.Y.Z. `.e.o.[.[.p.}.1.d.C.D.r.N.r.E.P.b.Q.F. + +.+.+++@+#+ ",
" $+%+&+*+ D =+L.[.<.1.1.1.C.d.-+r.r.;+;+b.F.G.Q.>+ +.+.+,+,+,+'+)+ ",
" !+~+{+!+ $ * ]+[.<.<.1.M.C.d.N.r.r.r.b.b.F.G.G.>+.+.+++,+,+^+/+A.(+} ",
" _+{.{.:+ @ <+L.[.[.[+}+|+d.d.r.r.r.O.P.b.S.G.T.1+2+++3+4+,+5+A.A.6+7+8+@ ",
" 9+#+0+a+ b+c+|.<.[+|+M.d.-+f.f.r.P.b.R.G.G.G.1+.+.+d+,+,+e+A.A.A.f+g+g+h+@ ",
" 8+i+i+9+ @ j+k+<.1.M.|+d.q.r.r.;+P.b.b.S.G.>+.+.+.+4+,+l+m+A.A.6+f+n+g+o+p+K ",
" q+r+r+8+ B s+1.1.M.d.d.-+q.r.P.P.b.Q.b.G.2+2+.+t+,+,+5+/+A.u+f+f+n+o+o+v+g.~ & ",
" w+x+y+z+ @ A+1.1.1.d.d.N.f.r.O.;+b.Q.Q.G..+.+.+,+,+e+e+A.A.A.f+B+C+D+o+E+F+g.G+H+@ ",
" I+J+K+h. y 3.2.1.d.D.e.r.E.r.b.b.F.G. + +.+.+t+d+,+5+A.L+L+6+D+o+g+M+v+g.g.N+s+O+~+ ",
" P+Q+R+S+ T+C.C.d.e.r.r.E.r.b.Q.Q.G.U+2+.+4+d+,+e+A.A.V+f+f+f+W+o+F+v+g.g.X+s+Y+Z+r @ ",
" `+l.l. @ # .@|+d.d.r.r.P.b.b.F.Q.G..+.+.+++t+5+,+A.A.f+f+f+f+o+o+E+v+g.X+G++@@@Y+@@#@$@ ",
" %@&@*@ @ =@2.D.D.r.O.O.t.R.-@G.G.2+T.4+,+,+l+A.m+A.6+6+f+W+g+;@>@g.,@X+s+Y+Y+'@@@3.3.)@) ",
" !@~@~@!@ @ @f.-+r.r.;+b.Q.S.G.G. +.+.+3+,+,+5+A.{@f+f+W+n+o+F+E+g.,@s+N+s++@@@@@#@3.3.]@^@ ",
" /@V.V.(@ & _@d.r.E.b.b.S.Q.G.1+T..+3+d+,+,+,+A.A.f+f+B+D+o+v+g.g.g.:@s+Z+<@@@[@3.3.}@]@]@|@& ",
" 1@2@3@1@ 4@q.r.P.t.-@5@-@G.1+.+t+.+d+,+5+A.A.f+f+f+W+B+o+o+g.g.X+X+s+6@<@@@7@3.3.}@]@]@8@9@0@ ",
" a@b@c@a@ @ d@r.P.t.b.G.G. +>+.+t+d+,+,+^+e+A.A.f+f+g+D+;@>@g.:@G+s++@Z+@@#@e@f@g@]@h@i@j@k@9@l@& ",
" m@n@n@o@ @ p@P.b.b.G.G..+.+.+++++,+^+/+A.u+L+f+C+o+o+v+E+g.,@,@s+6@6@@@[@f@3.q@r@}@s@k@9@t@u@v@w@ ",
" x@y@z@A@ Y s.R.-@S.G.1+U+B@t+,+,+^+^+V+{@6+f+B+W+o+F+g.g.N+X+s+6@@@@@C@7@g@D@}@]@9@i@t@9@u@v@E@F@@ ",
" G@H@I@J@ K@b.R.R.2+1+U+.+++3+m+,+5+A.f+f+n+W+n+F+E+M+,@s+s+6@6@@@@@e@3.q@D@r@j@k@8@u@L@v@M@N@O@O@P@ ",
" Q@=@R@S@ @ _ R.F.G..+.+.+4+3+5+l+e+V+7+f+n+g+o+o+g.g.g.G+s+s+s+@@C@f@3.]@3.h@i@i@9@9@v@v@M@N@T@U@V@W@# ",
" X@Y@Z@`@ #s+G.G.G..+++3+,+,+e+A.u+f+f+W+o+o+;@g.g..#g.s+s+@@@@3.e@3.D@D@]@]@s@9@+#v@v@v@O@O@@#V@##$#R@ ",
" %#&#*#=# -#G.>+1+.+d+++l+l+m+A.L+f+f+n+g+o+F+g.g.g.s+s+'@@@C@f@f@3.]@]@]@]@k@9@9@v@N@T@O@O@O@U@;#;#$#(.@ ",
" %#>#,#%# @ '# +.+.+++,+5+^+A.V+6+f+f+B+W+>@M+g.g.X+s+s+Y+Z+@@@@3.r@3.]@]@s@)#u@v@v@v@T@!#O@~#@###{#]#$#^#/# ",
" '#'.(#_# @ :#.+.+d+,+^+A.A.A.V+f+f+W+o+>@v+g.g.N+s++@@@@@@@3.3.D@g@]@8@s@9@<#+#v@M@[#O@O@O@V@##}#$#$#|#1#2#@ ",
" 3#4#5#6# b+o+d+++,+l+A.A.6+f+f+C+g+o+;@v+,@:@s+s+Y+6@@@7@f@3.3.h@]@j@9@9@9@v@v@v@T@O@7#V@######$#$#8#c+9#0#} ",
" a#`.b#c# d#t+d+,+5+/+A.7+f+f+o+W+F+>@F+g.G+s+s+Y+@@@@e@e@D@h@]@]@k@9@9@9@v@v@T@O@O@U@U@e#f#{#$#1#8#9#g#h#g#i# ",
" j#k#l#m# @ d@,+^+5+A.A.u+f+D+g+o+>@v+v+X+G+s+<@Z+@@@@3.3.}@]@]@]@)#9@9@v@v@N@[#O@7#V@####$#$#n#n#c+c+o#h#p#g#q#@ ",
" r#s#s#j# @ q#,+l+A.A.f+f+f+D+o+;@E+g.G+N+s+s+@@@@@@[@3.3.h@]@]@j@9@L@<#v@v@!#O@O@U@##f#f#$#n#n#c+o#g#g#t#t#=+u#b@ ",
" v#w#).x# 5 Y+A.V+V+u+f+B+W+o+;@;@g.,@g.s+Y+Z+@@3.7@q@g@}@j@]@9@9@u@v@v@T@!#O@@#U@##e#$#$#n#|#c+h#g#g#p#y#z#A#B#z+@ ",
" C#D#w#d@ E#m+A.A.f+n+n+g+o+o+M+g.,@s+s+@@Z+@@e@C@q@]@]@s@j@9@t@v@v@[#!#O@O@O@~###e#$#$#1#c+o#g#g#g#F#F#=+z#G#H#I#G ",
" J#K#L#M# @ N#A.7+f+n+W+o+o+;@g.X+:@s++@Y+@@@@e@3.q@g@]@i@)#9@9@L@v@N@O@O@O@V@##{#e#$#|#$#c+o#9#g#g#p#=+=+G#G#u.O#@+P#@ ",
" Q#R#S#Q# @ T#6+f+f+W+o+;@v+g.:@N+s+@@<@@@C@3.3.D@r@]@]@k@9@u@L@v@N@O@O@V@U@##e#$#$#n#c+c+U#^#g#g#F#=+=+u.u.V#H#@+W#X#- ",
" 2#Y#$@2# ^ )#f+f+D+o+v+F+g.g.G+s++@Y+@@3.7@3.D@h@]@i@8@9@L@Z#v@!#T@O@O+U@##;#}#$#n#|#c+^#g#g#_@=+=+G#u.H#u.V#@+`#m.m.$@ ",
" $.$+$@$ n@f+D+o+o+F+;@g..#:@+@s+@@[@f@3.D@q@]@]@j@8@9@u@L@v@E@O@O@O@##{#;#}#$#8#1#h#o#g##$=+t#=+A#B#$$%$@+@+@+&$m.*$=.@ ",
" =$-$-#;$ >$f+o+o+g.g.g.:@s+s+<@@@f@3.3.}@]@]@j@9@9@9@t@u@v@O@O@O@####;#$#$#n#1#c+c+U#g#t#y#=+=+A#u.$$%$$$@+,$m.m.'$'$p+Y ",
" )$h+!$=$ @ n o+o+v+g..#,@s++@@@@@@@e@3.r@}@]@j@s@9@Z#Z#N@[#O@O@O@@#;###;#$#$#~$o#c+g#g#g#t#{$u.u#u.H#%$@+]$m.m.^$'$/$'$U.($@ ",
" _$:$<$_$ $ =+v+E+g.G+s+Y+Y+<@C@f@[@g@]@]@s@)#9@t@Z#v@v@E@O@O@@#####]#]#$#n#c+9#^#g#g#g#y#=+u.u#u.V#%$@+@+m.m.'$[$'$'$}$U.|${ ",
" N#1$2$N# 3$E+v+N+:@N+s+<@@@@@7@3.3.h@h@s@j@9@9@+#v@[#[#T@~#V@O+##]#f#n#1#c+c+^#g##$_@=+z#{$u.u.$$@+W#@+m.^$*$'$4$4$5$6$U.7$8$ ",
" T+9$0$a$ @ b$g.X+s+s+'@'@@@@@3.f@g@]@]@)#j@9@u@L@v@N@O@O@O@######;#]#$#~$c+U#^#g#_@=+=+{$G#u.u.@+@+@+c$m.*$d$'$/$U.U.e$6$p+p+E @ ",
" f$g$h$T+ @ n N+G+s++@Z+@@f@3.3.g@}@]@]@8@<#<#+#v@N@!#O@~#@#e#;#{#$#n#c+c+h#g#g##$F#=+{$A#u.u.O#@+@+m.m.i$^$4$j$/$U.6$p+p+p+k$I#K+ ",
" l$m$n$o$ 5 7#s+s++@@@@@[@#@3.h@]@s@]@8@t@L@v@v@T@O@O@~###e#]#$#$#n#1#9#c+g#g##$=+=+u.G#u.@+@+@+m.m.m.m.'$'$5$U.e$p+p+p+I#I#'+p$q$@ ",
" r$s$t$($ u$:@s+<@@@f@3.3.g@}@]@]@j@8@9@L@v@v@[#O@V@####;#e#$#$#|#c+c+^#g#g#y#F#G#u#u.v$%$@+W#&$m.m.d$'$/$4$U.U.w$p+k$x$I#y$.@.@0#z$ ",
" A$B$B$C$ @ '#s+@@@@#@@@3.D@D@]@]@k@9@9@v@v@v@O@O@V@V@##f#$#$#$#c+c+c+h#g##$F#z#B#u.u.u.@+@+]$m.^$m.d$'$'$/$U.6$D$p+p+k$I#I#'+.@E$F$G$@ ",
" H$I$J$K$ @ L$@@@@C@C@3.q@h@i@]@9@9@9@u@v@v@!#O@@#~#{#{#;#$#c+~$c+U#U#g#y#=+z#B#A#O#u.H#@+`#&$d$i$'$'$'$M$6$w$7$N$O$I#y$P$p$.@E$Q$Q$)@^ ",
" R$S$T$U$ /#@@@@C@3.q@}@]@k@8@9@Z#u@v@v@T@O@7#O@##{#$#$#|#c+c+c+h#g#g#F#=+=+A#u.O#$$@+@+m.m.i$*$'$j$M$U.U.w$p+V$x$I#I#I#W$.@X$X$Q$Y$Z$`$ ",
" %.%.%+% @ @%@@C@3.q@g@]@]@i@9@9@v@v@v@N@O@~#V@####}#$#~$1#c+o#U#g#g#F#=+B#u.u.$$V#@+,$,$m.#%#%'$5$5$U.D$7$p+$%x$I#I#y$.@%%&%Q$*%Y$Z$Z$=%@ ",
" -%;%>%,% @ '%7@3.q@}@]@8@s@9@9@+#v@!#T@@#@#O+##{#$#)%n#)%c+o#U##$y#p#=+B#u.u.V#v$`#&$`#m.m.[$'$5$4$U.p+!%p+N$N$'+'+W$.@F$&%Q$~%{%Z$]%]%^%=@ ",
" /%(%_%/% ,.7#r@}@]@i@i@)#9@v@v@M@T@O@O@O+##{#;#$#$#|#c+c+^#g#g#g#F#=+u.u.u.H#%$,$@+&$m.#%[$/$5$U.7$!%p+k$x$I#I#I#.@F$Q$Q$Q$Y$Z$:%Z$^%^%<%Z @ ",
" H+[%[%}% @ |%D@3.]@]@j@9@t@Z#v@v@T@N@O@7###{#;#$#~$~$c+c+9#g#y#y#=+=+u.u#H#%$@+`#`#m.m.[$'$'$5$U.U.D$p+O$$%I#p$W$.@.@Q$Q$Q$1%Z$2%3%^%^%4%5%6%~@ ",
" >$7%0@8% @ E D@]@i@]@9@9@t@v@M@O@O@U@####f#}#$#)%c+c+^#h#g#g#_@=+{$G#u.H#@+@+c$@+m.^$*$'$j$U.U.U.!%p+p+k$I#y$9%.@%%Q$Q$Q$~%Z$2%]%^%^%0%5%6%0#z+@ ",
" a%b%c%d% V ~#s@]@)#t@<#Z#v@O@O@O@U@V@##}#}#$#$#c+c+^#h#g#g#t#=+u.u.u.u.V#@+&$W#m.i$[$'$/$j$U.e$D$p+p+I#y$y$.@.@F$X${%Q$Z$e%3%f%g%0%5%6%h%i%0#j%k% ",
" l%m%n%l% @ G@]@8@)#<#9@+#M@M@!#O+@###e#;#;#$#c+c+9#^#^#g#F#=+{$G#u.u.H#%$@+c$]$d$'$'$'$j$U.6$e$p+p+N$I#I#W$.@.@o%X$Q$~%p%Z$]%e%^%q%5%5%0#6%r%s%s%t%- ",
" u%v%v%w% K #$8@9@9@t@<#E@[#O@~#@#U@e#f#]#|#|#c+c+U#g#F#y#=+=+G#u.u.@+v$@+@+&$d$'$#%'$/$U.U.!%p+p+x$I#'+9%.@E$Q$Q$Q${%Z$2%:%^%x%g%5%5%h%0#y%z%j%A%B%m%@ ",
" _.5.C%_. @ D%)#9@9@L@v@v@!#O@O+V@####;#$#|#c+c+E%g#g#p#y#=+=+u.u.u.@+@+c$&$m.d$*$'$/$U.U.U.!%$%$%V$I#P$.@.@F$Q$Q$Q$Z$Z$e%]%^%q%q%5%F%0#y%y%z%j%j%B%G%H%I% ",
" J%K%L%M% I%I#9@<#v@v@N@T@O@@#V@##f#$#)%n#c+c+^#^#g#=+p#=+{$u#u.v$@+,$W#m.i$'$^$'$j$U.U.e$p+$%O$x$I#y$p$.@&%E${%*%Z$Z$Z$^%^%g%0%5%F%0#N%0#j%O%B%G%P%P%Q%R%@ ",
" G$S%T%U% @ =$Z#u@v@v@E@O@O@O@##;#]#$#$#)%8#E%h#g#g#y#=+z#G#u.u.v$@+`#c$m.m.'$'$/$U.U.6$p+!%p+I#x$I#.@.@o%.@Q$Q$*%1%Z$3%^%^%4%5%5%i%V%0#j%j%O%W%G%G%X%Y%Y%Z%Y. ",
" `% &.&G$ +&V#<#v@N@E@O@O@####;###$#)%|#c+c+h#g#g##$=+{$A#u.$$%$@+,$m.m.i$#%'$/$5$U.!%p+p+$%p+I#y$9%.@E$Q$Q$Y$Z$Z$e%^%^%^%0%5%V%h%0#0#@&j%W%G%G%X%Q%Y%Y%#&$&(.# ",
" %&&&*&=& - -&v@v@[#[#O@O@~#####{#$#n#~$9#9#g#g#y#F#=+{$G#u.u.V#@+`#@+m.m.d$'$5$}$U.!%w$p+N$k$y$'+.@F$o%Q$*%*%Z$]%e%^%^%^%q%5%V%V%0#0#y%j%B%B%;&;&;&Y%>&$&$&,&'&K@@ ",
" )&!&~&{& @ ]&v@v@M@O@O@V@##f#e#]#$#8#1#c+^#g#g#t#=+=+G#u.O#H#V#@+W#m.m.'$'$j$4$j$e$p+p+p+p+I#P$9%p$E$X$Q$Q$Y$Z$Z$3%^%^%x%x%^&0#i%y%s%s%W%A%A%G%P%Y%Y%/&$&(&_&:&:&<&b@@ ",
" K@[&[&}& @ |&8#N@E@O@O+@#######$#$#$#1#c+g#^#g#_@=+=+z#u.O#v$@+@+]$W#d$#%'$'$M$U.e$e$p+x$N$I#P$I#9%o%&%Q$*%1%1%]%^%^%g%0%5%5%F%0#0#0#j%1&G%G%2&X%Y%Y%#&/&_&,&:&L$L$L$3&&+@ ",
" 4&5&6&7& @ 8&'$v@O@!#7#O+##]#}#$#~$~$c+c+U#g##$=+=+{$z#u.V#V#@+@+&$m.^$*$'$4$j$U.U.7$p+$%I#I#P$P$.@.@&%Q$Q$~%Z$]%:%^%5%<%5%^&V%N%s%j%j%O%G%G%2&Y%Y%9&$&$&0&:&:&:&L$L$a&b&c&d&@ = % ",
" e&f&g&e& @ h&c+N@N@O@O+####]#}#n#n#c+9#o#h#g#y#=+B#u#u.u.u.@+`#`#W#m.[$'$'$j$/$U.w$p+p+$%O$I#W$.@.@E$Q$Q$*%p%Z$Z$^%^%0%5%5%h%^&z%@&z%O%W%G%G%;&P%Y%#&$&$&0&:&:&L$i&L$j&j&j&j&p@J$@ = % . . ",
" !&k&l&m&J.J.@%n&e&4&K@)&%&`%G$J%_.u%l%a%>$H+/%-% %R$H$A$r$l$f$T+N#_$)$=$ $2#Q#J#C#v#r#j#a#3#'#%#%#X@Q@G@x@m@a@1@/@!@%@`+P+I+w+q+8+9+_+!+$+W.H.w.i.6.].=.$.` ` X T Q M I I F C A w u r n j h d a 8 4 | [ _ ] ~ ' = & $ . . . ",
" o&p&q&r&K@s&t&u&f&5&[&!&&& &S%K%5.v%m%b%7%[%(%;%.%S$I$B$s$m$g$9$1$:$h+-$.$Y#R#K#D#w#s#k#`.4#'.>#&#Y@=@H@y@n@b@2@V.~@&@l.Q+J+x+r+i+#+{.~+%+X.I.x.j.7.^.-.%.@. .Y U R N L J G D B x v s o k i e b 9 5 1 } : ^ { ) - & $ # + . . . ",
" o&p&q&r&4&s&t&v&g&6&[&~&*&.&T%L%C%v%n%c%0@[%_%>%.%T$J$B$t$n$h$0$2$<$!$-#+$$@S#L#w#).s#l#b#5#(#,#*#Z@R@I@z@n@c@3@V.~@*@l.R+K+y+r+i+0+{.{+&+Y.I.y.k.8./.;.&.#...Y V S O L K G D B y v s p l i f c 0 6 2 } ^ / { ) - & $ # @ . . . ",
" w&k&l&x&y&z&t&A&e&7&}&{&=&G$U%M%_.w%l%d%8%}%/%,%+%U$K$C$($o$T+a$N#_$=$;$@$2#Q#M#d@x#j#m#c#6#_#%#=#`@S@J@A@o@a@1@(@!@ @ @S+h.z+8+9+a+:+!+*+Z.H.i.6.9.(.>.*.` +.Z W Q P I F H E A z u t q m h g a 4 7 3 _ < ( ~ ! ; & $ . . . ",
" m&r&r&x& > * . . ",
" l&q&q&l& , * ",
" k&p&p&k& ",
" !&o&o&w& ",
" ",
" ",
" ",
" ",
" ",
" "};

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/Mod/Ship/Icons/Ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
src/Mod/Ship/Icons/Ico.xcf Normal file

Binary file not shown.

1281
src/Mod/Ship/Icons/Ico.xpm Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/Mod/Ship/Icons/Ship.xcf Normal file

Binary file not shown.

431
src/Mod/Ship/Icons/Ship.xpm Normal file
View File

@@ -0,0 +1,431 @@
/* XPM */
static char * Ship_xpm[] = {
"32 32 396 2",
" c None",
". c #2C2C2C",
"+ c #3A3A3A",
"@ c #585857",
"# c #161616",
"$ c #000000",
"% c #363636",
"& c #333333",
"* c #B3B3B3",
"= c #B4B4B4",
"- c #949494",
"; c #565653",
"> c #141414",
", c #080807",
"' c #585858",
") c #878787",
"! c #9F9E9F",
"~ c #9F9F9E",
"{ c #8F8F90",
"] c #6B6B6B",
"^ c #101010",
"/ c #737373",
"( c #4C4C4C",
"_ c #B1B1B7",
": c #9090C0",
"< c #A7A7B2",
"[ c #87878E",
"} c #4F4F52",
"| c #191919",
"1 c #656565",
"2 c #D1D1D2",
"3 c #D1D1D1",
"4 c #CECECE",
"5 c #CDCCCC",
"6 c #CCCCCC",
"7 c #CCCCCB",
"8 c #CDCECD",
"9 c #BDBDBD",
"0 c #424242",
"a c #373737",
"b c #0A0A0A",
"c c #241414",
"d c #0E0C0C",
"e c #929393",
"f c #383738",
"g c #9B9B9A",
"h c #A0A0AF",
"i c #2929E4",
"j c #2525E5",
"k c #3F3FD7",
"l c #5B5BC8",
"m c #535368",
"n c #686866",
"o c #C8C8C8",
"p c #C8C8C7",
"q c #C7C6C7",
"r c #C6C6C6",
"s c #C5C5C5",
"t c #C4C5C5",
"u c #C3C4C3",
"v c #C3C3C2",
"w c #BCBCBC",
"x c #595959",
"y c #A6A6A6",
"z c #969696",
"A c #0B0B0B",
"B c #0D0707",
"C c #894646",
"D c #1C1A1A",
"E c #525252",
"F c #6C6D6C",
"G c #A3A3A2",
"H c #A3A296",
"I c #8E8F98",
"J c #6F6EA5",
"K c #5354AF",
"L c #373753",
"M c #8D8D8B",
"N c #C5C5C4",
"O c #C2C2C2",
"P c #C1C1C1",
"Q c #C0C0C0",
"R c #C0BFBF",
"S c #BFBFBF",
"T c #BEBEBE",
"U c #B1B2B2",
"V c #404040",
"W c #ABAAAA",
"X c #797979",
"Y c #2A1212",
"Z c #662828",
"` c #3D403F",
" . c #B5B5B5",
".. c #6B6A6B",
"+. c #4A4A4A",
"@. c #9A9A9A",
"#. c #909090",
"$. c #8B8B8A",
"%. c #898A86",
"&. c #84837F",
"*. c #3D3D3C",
"=. c #9E9E9E",
"-. c #BFBFBE",
";. c #BDBEBD",
">. c #BBBBBB",
",. c #BABABA",
"'. c #B9B9B9",
"). c #B8B8B8",
"!. c #999999",
"~. c #BABAB9",
"{. c #ABABAB",
"]. c #292929",
"^. c #381212",
"/. c #4C1514",
"(. c #535656",
"_. c #717171",
":. c #919090",
"<. c #818181",
"[. c #4E4E4E",
"}. c #4B4B4B",
"|. c #B1B1B1",
"1. c #B8B7B8",
"2. c #B6B6B6",
"3. c #B6B5B5",
"4. c #B4B5B4",
"5. c #B2B3B2",
"6. c #5C5D5C",
"7. c #AFAFAF",
"8. c #ADACAC",
"9. c #5B5B5B",
"0. c #410C0C",
"a. c #3E0707",
"b. c #525555",
"c. c #9C9C9C",
"d. c #2D2D2D",
"e. c #757575",
"f. c #474747",
"g. c #484848",
"h. c #9F9F9F",
"i. c #B3B3B4",
"j. c #B2B2B2",
"k. c #B0B0B0",
"l. c #ADAEAD",
"m. c #ADADAD",
"n. c #B0B1B0",
"o. c #1E1E1E",
"p. c #ACABAC",
"q. c #AAA9A9",
"r. c #A8A8A8",
"s. c #5D5D5D",
"t. c #290202",
"u. c #281010",
"v. c #272828",
"w. c #767777",
"x. c #505050",
"y. c #1F1F1F",
"z. c #5E5E5D",
"A. c #A4A5A5",
"B. c #B1B2B1",
"C. c #AEAEAE",
"D. c #AEADAD",
"E. c #ABACAC",
"F. c #AAAAAA",
"G. c #A9A8A8",
"H. c #ABABAC",
"I. c #7B7B7B",
"J. c #2B2B2B",
"K. c #A4A4A4",
"L. c #A6A5A6",
"M. c #888888",
"N. c #0E0E0E",
"O. c #101312",
"P. c #7E8080",
"Q. c #5E5E5E",
"R. c #242424",
"S. c #555555",
"T. c #7F7F7F",
"U. c #A4A3A4",
"V. c #B3B3B2",
"W. c #ACACAC",
"X. c #A9A9A9",
"Y. c #A8A7A7",
"Z. c #A7A6A7",
"`. c #A7A7A7",
" + c #A8A8A7",
".+ c #A5A5A5",
"++ c #A2A2A2",
"@+ c #222122",
"#+ c #7E7E7E",
"$+ c #A3A3A3",
"%+ c #9B9B9B",
"&+ c #050505",
"*+ c #6E6E6E",
"=+ c #A7A7A6",
"-+ c #989898",
";+ c #A5A4A4",
">+ c #A7A7A8",
",+ c #A5A6A7",
"'+ c #979A99",
")+ c #818383",
"!+ c #757878",
"~+ c #757979",
"{+ c #878A8A",
"]+ c #A3A5A5",
"^+ c #828282",
"/+ c #A0A0A0",
"(+ c #232323",
"_+ c #939393",
":+ c #A5A6A5",
"<+ c #A2A3A2",
"[+ c #A2A1A1",
"}+ c #A1A0A1",
"|+ c #939292",
"1+ c #636262",
"2+ c #554D4D",
"3+ c #634C4C",
"4+ c #755555",
"5+ c #936464",
"6+ c #9F6868",
"7+ c #9B6060",
"8+ c #804A4A",
"9+ c #5C3737",
"0+ c #1D1616",
"a+ c #A1A1A1",
"b+ c #010101",
"c+ c #151516",
"d+ c #707070",
"e+ c #9D9E9E",
"f+ c #8C8D8D",
"g+ c #8B8888",
"h+ c #726A6A",
"i+ c #6D5959",
"j+ c #866261",
"k+ c #C18B8B",
"l+ c #D79696",
"m+ c #D18C8C",
"n+ c #CB8180",
"o+ c #C57575",
"p+ c #BF6B6A",
"q+ c #BB6161",
"r+ c #B95958",
"s+ c #9C4544",
"t+ c #2E1212",
"u+ c #6F6C6C",
"v+ c #A0A1A1",
"w+ c #575757",
"x+ c #0C0C0C",
"y+ c #9C9D9D",
"z+ c #7A7272",
"A+ c #876F6F",
"B+ c #977070",
"C+ c #C28C8C",
"D+ c #D59595",
"E+ c #D08A8A",
"F+ c #C67D7D",
"G+ c #C07272",
"H+ c #BC6969",
"I+ c #B85F5F",
"J+ c #B35656",
"K+ c #B04C4C",
"L+ c #AB4243",
"M+ c #A63939",
"N+ c #591B1B",
"O+ c #6A2121",
"P+ c #542323",
"Q+ c #585A5A",
"R+ c #191515",
"S+ c #706262",
"T+ c #A58080",
"U+ c #B58383",
"V+ c #CE8F8F",
"W+ c #CD8989",
"X+ c #C17372",
"Y+ c #B45656",
"Z+ c #AF4C4C",
"`+ c #AB4242",
" @ c #A73A39",
".@ c #A3302F",
"+@ c #9F2626",
"@@ c #8E1A1A",
"#@ c #2C0808",
"$@ c #91191A",
"%@ c #2F0200",
"&@ c #90C6FB",
"*@ c #8BBFFB",
"=@ c #94CBFC",
"-@ c #AFEFFB",
";@ c #7DABA0",
">@ c #3C2521",
",@ c #C88484",
"'@ c #C57C7D",
")@ c #C17273",
"!@ c #B86060",
"~@ c #AB4343",
"{@ c #A73939",
"]@ c #A32F2F",
"^@ c #9B1C1D",
"/@ c #961313",
"(@ c #96090A",
"_@ c #3C0202",
":@ c #4E0202",
"<@ c #300000",
"[@ c #3E5378",
"}@ c #7EABF9",
"|@ c #84B5FC",
"1@ c #96CDFB",
"2@ c #B2F2FA",
"3@ c #C4FFFA",
"4@ c #2E3FFD",
"5@ c #3346FD",
"6@ c #2A3AFD",
"7@ c #161EFE",
"8@ c #1B25FD",
"9@ c #1F25B4",
"0@ c #7C6196",
"a@ c #AA6075",
"b@ c #AC5763",
"c@ c #AD5155",
"d@ c #AD4645",
"e@ c #A83938",
"f@ c #A3302E",
"g@ c #A02624",
"h@ c #9B1C1B",
"i@ c #971311",
"j@ c #930A09",
"k@ c #900300",
"l@ c #900505",
"m@ c #660007",
"n@ c #00000D",
"o@ c #200112",
"p@ c #597F88",
"q@ c #6E97FD",
"r@ c #384CFD",
"s@ c #394EFD",
"t@ c #2D3EFD",
"u@ c #151DFE",
"v@ c #1821FE",
"w@ c #3C52FD",
"x@ c #6388FC",
"y@ c #9CD6FB",
"z@ c #D0FFFA",
"A@ c #AEEEFB",
"B@ c #749FFF",
"C@ c #3F5DFF",
"D@ c #4165FF",
"E@ c #525AE3",
"F@ c #6153C4",
"G@ c #672D8D",
"H@ c #6C1B6A",
"I@ c #722164",
"J@ c #75225E",
"K@ c #731D57",
"L@ c #701653",
"M@ c #690E52",
"N@ c #5F0050",
"O@ c #562086",
"P@ c #11108D",
"Q@ c #2330BE",
"R@ c #344AE1",
"S@ c #4E6BFF",
"T@ c #4E6BFD",
"U@ c #597AFC",
"V@ c #6184FC",
"W@ c #7099FC",
"X@ c #8BBEFB",
"Y@ c #95CCFB",
"Z@ c #5B7CFC",
"`@ c #1C26FD",
" # c #121AFE",
".# c #9ED7FB",
"+# c #81B4FF",
"@# c #6893FF",
"## c #6997FF",
"$# c #6695FF",
"%# c #6390FF",
"&# c #618DFF",
"*# c #608DFF",
"=# c #618EFF",
"-# c #6391FF",
";# c #6898FF",
"># c #6B9AFF",
",# c #5171ED",
"'# c #90C4FF",
")# c #7EABFC",
"!# c #729CFC",
"~# c #6287FC",
"{# c #4761FD",
"]# c #070AFE",
"^# c #6084FC",
"/# c #9AD2FB",
"(# c #A2DDFB",
"_# c #8ABDFB",
":# c #2B3AFD",
"<# c #A9E8FB",
"[# c #B9FCFA",
"}# c #BAFEFA",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . + @ # $ $ $ $ $ ",
" % & * = - ; > $ $ , ' ) ! ~ { ] & $ $ $ ",
" ^ / ( = _ : < [ } | $ 1 2 3 4 5 6 7 6 8 9 0 a b ",
" c d e f g h i j k l m n 4 o p q r s t u v w x y z A ",
" B C D * E F G H I J K L M N O O P Q R S T 9 U V W O X $ ",
" Y Z ` ...+.@.#.$.%.&.*.=.-.;.w >.>.,.'.).).!.+ ~. .{.]. ",
" ^./.(.y _.f :.) <.[.^ }.|.).1.2.3. .4.* 5. .6.1 4.7.8.9. ",
" 0.a.b.c./ d.e.f.| g.h.9 i.* j.|.k.7.7.l.m.n.o.@.p.q.r.s. ",
" t.u.v.w.x.y.% z.A.).B.C.D.m.E.{.F.F.G.r.H.I.J.k.K.L.M.N. ",
" O.P.Q.R.S.T.U.V.W.q.X.r.Y.Z.`.Y. +`..+++{.@+#+$+++%+y. ",
" &+*+W.=+-+;+X.>+y .+K.K.y y ,+'+)+!+~+{+]+^+].$+/+$+J. ",
" (+_+:+U.$+<+[+}+/+h.=.|+1+2+3+4+5+6+7+8+9+0+_.a+/+0 b+ ",
" c+d+h.a+/+++e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+$ ",
" x+f.- y+w.z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+$ ",
" R+S+T+U+V+W+F+X+H+I+Y+Z+`+ @.@+@@@#@$@%@$ ",
"&@*@=@-@;@>@,@'@)@H+!@Y+K+~@{@]@+@^@/@(@_@:@<@[@}@|@1@2@3@ ",
"4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@",
" z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #",
" .#+#@###$#%#&#*#=#-#;#>#,#'# )#!#~#{#]#^#/#",
" (#_#:#<#",
" [#}#",
" ",
" ",
" ",
" "};

42
src/Mod/Ship/InitGui.py Normal file
View File

@@ -0,0 +1,42 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
class ShipWorkbench ( Workbench ):
""" @brief Workbench of Ship design module. Here toolbars & icons are append. """
from shipUtils import Paths, Translator
import ShipGui
Icon = Paths.iconsPath() + "/Ico.png"
MenuText = str(Translator.translate("Ship design"))
ToolTip = str(Translator.translate("Ship design"))
def Initialize(self):
# ToolBar
list = ["Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve"]
self.appendToolbar("Ship design",list)
# Menu
list = ["Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve"]
self.appendMenu("Ship design",list)
Gui.addWorkbench(ShipWorkbench())

669
src/Mod/Ship/Instance.py Normal file
View File

@@ -0,0 +1,669 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import time
# COIN
from pivy.coin import *
from pivy import coin
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base, Vector
# Ship design module
from shipUtils import Paths, Translator, Math
class Ship:
def __init__(self, obj, faces):
""" Creates a new ship on active document.
@param faces Ship faces (Part::Shape entities).
"""
self.faces = faces
# Add uniqueness property to identify Ship instances
obj.addProperty("App::PropertyBool","IsShip","Ship", str(Translator.translate("True if is a valid ship instance"))).IsShip=True
# Add main dimensions
obj.addProperty("App::PropertyLength","Length","Ship", str(Translator.translate("Ship length (Lpp) [m]"))).Length=0.0
obj.addProperty("App::PropertyLength","Beam","Ship", str(Translator.translate("Ship beam (B) [m]"))).Beam=0.0
obj.addProperty("App::PropertyLength","Draft","Ship", str(Translator.translate("Ship draft (T) [m]"))).Draft=0.0
# Add shapes
obj.addProperty("Part::PropertyPartShape","Shape","Ship", str(Translator.translate("Ship surfaces"))).Shape = Part.makeShell(self.faces)
obj.Proxy = self
self.obj = obj
def onChanged(self, fp, prop):
''' Print the name of the property that has changed '''
# FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
if prop == "Length" or prop == "Beam" or prop == "Draft":
fp.Shape = Part.makeShell(self.faces)
def execute(self, obj):
''' Print a short message when doing a recomputation, this method is mandatory '''
# FreeCAD.Console.PrintMessage("Recompute Ship\n")
obj.Shape = Part.makeShell(self.faces)
def lineFaceSection(self,line,surface):
""" Returns the point of section of a line with a face
@param line Line object, that can be a curve.
@param surface Surface object (must be a Part::Shape)
@return Section points array, [] if line don't cut surface
"""
# Get initial data
result = []
vertexes = line.Vertexes
nVertex = len(vertexes)
# Perform the cut
section = line.cut(surface)
# Filter all old points
points = section.Vertexes
nPoint = len(points)
if nPoint <= nVertex:
# Any valid point
return result
for i in range(0,nPoint):
disp = len(result)
flag = 0
if not Math.isAprox(points[i].X,vertexes[i-disp].X,0.0001):
flag = flag+1
if not Math.isAprox(points[i].Y,vertexes[i-disp].Y,0.0001):
flag = flag+1
if not Math.isAprox(points[i].Z,vertexes[i-disp].Z,0.0001):
flag = flag+1
if flag > 0:
result.append(points[i])
return result
def discretize(self, nS, nP):
""" Discretize the surface.
@param nS Number of sections
@param nP Number of points per section
"""
self.obj.addProperty("App::PropertyInteger","nSections","Ship", str(Translator.translate("Number of sections"))).nSections=nS
self.obj.addProperty("App::PropertyIntegerList","nPoints","Ship", str(Translator.translate("List of number of points per sections (accumulated histogram)"))).nPoints=[0]
self.obj.addProperty("App::PropertyFloatList","xSection","Ship", str(Translator.translate("List of sections x coordinate"))).xSection=[]
self.obj.addProperty("App::PropertyVectorList","mSections","Ship", str(Translator.translate("List of sections points"))).mSections=[]
nPoints = [0]
xSection = []
mSections = []
# Get bounds
shape = self.obj.Shape
bbox = shape.BoundBox
x0 = bbox.XMin
x1 = bbox.XMax
y0 = bbox.YMin
y1 = bbox.YMax
z0 = bbox.ZMin
z1 = bbox.ZMax
# Create a set of planes to perfom edges sections
planes = []
dz = (z1 - z0) / (nP - 1)
for j in range(0,nP):
z = z0 + j*dz
rX = x1 - x0
rY = y1 - y0
planes.append(Part.makePlane(4*rX,4*rY,Base.Vector(-2*rX,-2*rY,z),Base.Vector(0,0,1)))
# Division are performed at x axis
dx = (x1 - x0) / (nS - 1.0)
for i in range(0,nS):
section = []
x = x0 + i*dx
xSection.append(x)
percen = i*100 / (nS-1)
FreeCAD.Console.PrintMessage('%d%%\n' % (percen));
# Slice the surface to get curves
wires = shape.slice(Vector(1.0,0.0,0.0), x)
if not wires:
if (i != 0) or (i != nS-1):
msg = 'Found empty section at x=%g\n'
msg = Translator.translate(msg)
FreeCAD.Console.PrintWarning(msg)
FreeCAD.Console.PrintWarning('\tThis may happens if a bad defined (or really complex) surface has been provided.\n')
FreeCAD.Console.PrintWarning('\tPlease, ensure that this section is correct, or fix surfaces and create a new ship.\n')
nPoints.append(0)
# Desarrollate wires into edges list
edges = []
for j in range(0,len(wires)):
wire = wires[j].Edges
for k in range(0,len(wire)):
edges.append(wire[k])
# Slice curves to get points (Length based)
points = []
for j in range(0,len(edges)):
for k in range(0,nP):
aux = self.lineFaceSection(edges[j], planes[k])
if not aux:
points.append(Vector(x,0,z0 + k*dz))
for l in range(0,len(aux)):
points.append(Vector(aux[l].X, aux[l].Y, aux[l].Z))
# Sort section points at Y direction
aux = []
for j in range(0,len(points)):
aux.append(points[j].y)
aux.sort()
for j in range(0,len(points)):
section.append(Vector(points[j].x, aux[j], points[j].z))
# Store points
nPoints.append(len(section))
for j in range(0,len(section)):
mSections.append(section[j])
# Save data
for i in range(1,len(nPoints)):
nPoints[i] = nPoints[i] + nPoints[i-1]
self.obj.nPoints = nPoints[:]
self.obj.xSection = xSection[:]
self.obj.mSections = mSections[:]
class ViewProviderShip:
def __init__(self, obj):
"Set this object to the proxy object of the actual view provider"
obj.Proxy = self
def attach(self, obj):
''' Setup the scene sub-graph of the view provider, this method is mandatory '''
return
def updateData(self, fp, prop):
''' If a property of the handled feature has changed we have the chance to handle this here '''
return
def getDisplayModes(self,obj):
''' Return a list of display modes. '''
modes=[]
return modes
def getDefaultDisplayMode(self):
''' Return the name of the default display mode. It must be defined in getDisplayModes. '''
return "Shaded"
def setDisplayMode(self,mode):
''' Map the display mode defined in attach with those defined in getDisplayModes.
Since they have the same names nothing needs to be done. This method is optinal.
'''
return mode
def onChanged(self, vp, prop):
''' Print the name of the property that has changed '''
# FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
def __getstate__(self):
''' When saving the document this object gets stored using Python's cPickle module.
Since we have some un-pickable here -- the Coin stuff -- we must define this method
to return a tuple of all pickable objects or None.
'''
return None
def __setstate__(self,state):
''' When restoring the pickled object from document we have the chance to set some
internals here. Since no data were pickled nothing needs to be done here.
'''
return None
def getIcon(self):
return """
/* XPM */
static char * Ship_xpm[] = {
"32 32 396 2",
" c None",
". c #2C2C2C",
"+ c #3A3A3A",
"@ c #585857",
"# c #161616",
"$ c #000000",
"% c #363636",
"& c #333333",
"* c #B3B3B3",
"= c #B4B4B4",
"- c #949494",
"; c #565653",
"> c #141414",
", c #080807",
"' c #585858",
") c #878787",
"! c #9F9E9F",
"~ c #9F9F9E",
"{ c #8F8F90",
"] c #6B6B6B",
"^ c #101010",
"/ c #737373",
"( c #4C4C4C",
"_ c #B1B1B7",
": c #9090C0",
"< c #A7A7B2",
"[ c #87878E",
"} c #4F4F52",
"| c #191919",
"1 c #656565",
"2 c #D1D1D2",
"3 c #D1D1D1",
"4 c #CECECE",
"5 c #CDCCCC",
"6 c #CCCCCC",
"7 c #CCCCCB",
"8 c #CDCECD",
"9 c #BDBDBD",
"0 c #424242",
"a c #373737",
"b c #0A0A0A",
"c c #241414",
"d c #0E0C0C",
"e c #929393",
"f c #383738",
"g c #9B9B9A",
"h c #A0A0AF",
"i c #2929E4",
"j c #2525E5",
"k c #3F3FD7",
"l c #5B5BC8",
"m c #535368",
"n c #686866",
"o c #C8C8C8",
"p c #C8C8C7",
"q c #C7C6C7",
"r c #C6C6C6",
"s c #C5C5C5",
"t c #C4C5C5",
"u c #C3C4C3",
"v c #C3C3C2",
"w c #BCBCBC",
"x c #595959",
"y c #A6A6A6",
"z c #969696",
"A c #0B0B0B",
"B c #0D0707",
"C c #894646",
"D c #1C1A1A",
"E c #525252",
"F c #6C6D6C",
"G c #A3A3A2",
"H c #A3A296",
"I c #8E8F98",
"J c #6F6EA5",
"K c #5354AF",
"L c #373753",
"M c #8D8D8B",
"N c #C5C5C4",
"O c #C2C2C2",
"P c #C1C1C1",
"Q c #C0C0C0",
"R c #C0BFBF",
"S c #BFBFBF",
"T c #BEBEBE",
"U c #B1B2B2",
"V c #404040",
"W c #ABAAAA",
"X c #797979",
"Y c #2A1212",
"Z c #662828",
"` c #3D403F",
" . c #B5B5B5",
".. c #6B6A6B",
"+. c #4A4A4A",
"@. c #9A9A9A",
"#. c #909090",
"$. c #8B8B8A",
"%. c #898A86",
"&. c #84837F",
"*. c #3D3D3C",
"=. c #9E9E9E",
"-. c #BFBFBE",
";. c #BDBEBD",
">. c #BBBBBB",
",. c #BABABA",
"'. c #B9B9B9",
"). c #B8B8B8",
"!. c #999999",
"~. c #BABAB9",
"{. c #ABABAB",
"]. c #292929",
"^. c #381212",
"/. c #4C1514",
"(. c #535656",
"_. c #717171",
":. c #919090",
"<. c #818181",
"[. c #4E4E4E",
"}. c #4B4B4B",
"|. c #B1B1B1",
"1. c #B8B7B8",
"2. c #B6B6B6",
"3. c #B6B5B5",
"4. c #B4B5B4",
"5. c #B2B3B2",
"6. c #5C5D5C",
"7. c #AFAFAF",
"8. c #ADACAC",
"9. c #5B5B5B",
"0. c #410C0C",
"a. c #3E0707",
"b. c #525555",
"c. c #9C9C9C",
"d. c #2D2D2D",
"e. c #757575",
"f. c #474747",
"g. c #484848",
"h. c #9F9F9F",
"i. c #B3B3B4",
"j. c #B2B2B2",
"k. c #B0B0B0",
"l. c #ADAEAD",
"m. c #ADADAD",
"n. c #B0B1B0",
"o. c #1E1E1E",
"p. c #ACABAC",
"q. c #AAA9A9",
"r. c #A8A8A8",
"s. c #5D5D5D",
"t. c #290202",
"u. c #281010",
"v. c #272828",
"w. c #767777",
"x. c #505050",
"y. c #1F1F1F",
"z. c #5E5E5D",
"A. c #A4A5A5",
"B. c #B1B2B1",
"C. c #AEAEAE",
"D. c #AEADAD",
"E. c #ABACAC",
"F. c #AAAAAA",
"G. c #A9A8A8",
"H. c #ABABAC",
"I. c #7B7B7B",
"J. c #2B2B2B",
"K. c #A4A4A4",
"L. c #A6A5A6",
"M. c #888888",
"N. c #0E0E0E",
"O. c #101312",
"P. c #7E8080",
"Q. c #5E5E5E",
"R. c #242424",
"S. c #555555",
"T. c #7F7F7F",
"U. c #A4A3A4",
"V. c #B3B3B2",
"W. c #ACACAC",
"X. c #A9A9A9",
"Y. c #A8A7A7",
"Z. c #A7A6A7",
"`. c #A7A7A7",
" + c #A8A8A7",
".+ c #A5A5A5",
"++ c #A2A2A2",
"@+ c #222122",
"#+ c #7E7E7E",
"$+ c #A3A3A3",
"%+ c #9B9B9B",
"&+ c #050505",
"*+ c #6E6E6E",
"=+ c #A7A7A6",
"-+ c #989898",
";+ c #A5A4A4",
">+ c #A7A7A8",
",+ c #A5A6A7",
"'+ c #979A99",
")+ c #818383",
"!+ c #757878",
"~+ c #757979",
"{+ c #878A8A",
"]+ c #A3A5A5",
"^+ c #828282",
"/+ c #A0A0A0",
"(+ c #232323",
"_+ c #939393",
":+ c #A5A6A5",
"<+ c #A2A3A2",
"[+ c #A2A1A1",
"}+ c #A1A0A1",
"|+ c #939292",
"1+ c #636262",
"2+ c #554D4D",
"3+ c #634C4C",
"4+ c #755555",
"5+ c #936464",
"6+ c #9F6868",
"7+ c #9B6060",
"8+ c #804A4A",
"9+ c #5C3737",
"0+ c #1D1616",
"a+ c #A1A1A1",
"b+ c #010101",
"c+ c #151516",
"d+ c #707070",
"e+ c #9D9E9E",
"f+ c #8C8D8D",
"g+ c #8B8888",
"h+ c #726A6A",
"i+ c #6D5959",
"j+ c #866261",
"k+ c #C18B8B",
"l+ c #D79696",
"m+ c #D18C8C",
"n+ c #CB8180",
"o+ c #C57575",
"p+ c #BF6B6A",
"q+ c #BB6161",
"r+ c #B95958",
"s+ c #9C4544",
"t+ c #2E1212",
"u+ c #6F6C6C",
"v+ c #A0A1A1",
"w+ c #575757",
"x+ c #0C0C0C",
"y+ c #9C9D9D",
"z+ c #7A7272",
"A+ c #876F6F",
"B+ c #977070",
"C+ c #C28C8C",
"D+ c #D59595",
"E+ c #D08A8A",
"F+ c #C67D7D",
"G+ c #C07272",
"H+ c #BC6969",
"I+ c #B85F5F",
"J+ c #B35656",
"K+ c #B04C4C",
"L+ c #AB4243",
"M+ c #A63939",
"N+ c #591B1B",
"O+ c #6A2121",
"P+ c #542323",
"Q+ c #585A5A",
"R+ c #191515",
"S+ c #706262",
"T+ c #A58080",
"U+ c #B58383",
"V+ c #CE8F8F",
"W+ c #CD8989",
"X+ c #C17372",
"Y+ c #B45656",
"Z+ c #AF4C4C",
"`+ c #AB4242",
" @ c #A73A39",
".@ c #A3302F",
"+@ c #9F2626",
"@@ c #8E1A1A",
"#@ c #2C0808",
"$@ c #91191A",
"%@ c #2F0200",
"&@ c #90C6FB",
"*@ c #8BBFFB",
"=@ c #94CBFC",
"-@ c #AFEFFB",
";@ c #7DABA0",
">@ c #3C2521",
",@ c #C88484",
"'@ c #C57C7D",
")@ c #C17273",
"!@ c #B86060",
"~@ c #AB4343",
"{@ c #A73939",
"]@ c #A32F2F",
"^@ c #9B1C1D",
"/@ c #961313",
"(@ c #96090A",
"_@ c #3C0202",
":@ c #4E0202",
"<@ c #300000",
"[@ c #3E5378",
"}@ c #7EABF9",
"|@ c #84B5FC",
"1@ c #96CDFB",
"2@ c #B2F2FA",
"3@ c #C4FFFA",
"4@ c #2E3FFD",
"5@ c #3346FD",
"6@ c #2A3AFD",
"7@ c #161EFE",
"8@ c #1B25FD",
"9@ c #1F25B4",
"0@ c #7C6196",
"a@ c #AA6075",
"b@ c #AC5763",
"c@ c #AD5155",
"d@ c #AD4645",
"e@ c #A83938",
"f@ c #A3302E",
"g@ c #A02624",
"h@ c #9B1C1B",
"i@ c #971311",
"j@ c #930A09",
"k@ c #900300",
"l@ c #900505",
"m@ c #660007",
"n@ c #00000D",
"o@ c #200112",
"p@ c #597F88",
"q@ c #6E97FD",
"r@ c #384CFD",
"s@ c #394EFD",
"t@ c #2D3EFD",
"u@ c #151DFE",
"v@ c #1821FE",
"w@ c #3C52FD",
"x@ c #6388FC",
"y@ c #9CD6FB",
"z@ c #D0FFFA",
"A@ c #AEEEFB",
"B@ c #749FFF",
"C@ c #3F5DFF",
"D@ c #4165FF",
"E@ c #525AE3",
"F@ c #6153C4",
"G@ c #672D8D",
"H@ c #6C1B6A",
"I@ c #722164",
"J@ c #75225E",
"K@ c #731D57",
"L@ c #701653",
"M@ c #690E52",
"N@ c #5F0050",
"O@ c #562086",
"P@ c #11108D",
"Q@ c #2330BE",
"R@ c #344AE1",
"S@ c #4E6BFF",
"T@ c #4E6BFD",
"U@ c #597AFC",
"V@ c #6184FC",
"W@ c #7099FC",
"X@ c #8BBEFB",
"Y@ c #95CCFB",
"Z@ c #5B7CFC",
"`@ c #1C26FD",
" # c #121AFE",
".# c #9ED7FB",
"+# c #81B4FF",
"@# c #6893FF",
"## c #6997FF",
"$# c #6695FF",
"%# c #6390FF",
"&# c #618DFF",
"*# c #608DFF",
"=# c #618EFF",
"-# c #6391FF",
";# c #6898FF",
"># c #6B9AFF",
",# c #5171ED",
"'# c #90C4FF",
")# c #7EABFC",
"!# c #729CFC",
"~# c #6287FC",
"{# c #4761FD",
"]# c #070AFE",
"^# c #6084FC",
"/# c #9AD2FB",
"(# c #A2DDFB",
"_# c #8ABDFB",
":# c #2B3AFD",
"<# c #A9E8FB",
"[# c #B9FCFA",
"}# c #BAFEFA",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . + @ # $ $ $ $ $ ",
" % & * = - ; > $ $ , ' ) ! ~ { ] & $ $ $ ",
" ^ / ( = _ : < [ } | $ 1 2 3 4 5 6 7 6 8 9 0 a b ",
" c d e f g h i j k l m n 4 o p q r s t u v w x y z A ",
" B C D * E F G H I J K L M N O O P Q R S T 9 U V W O X $ ",
" Y Z ` ...+.@.#.$.%.&.*.=.-.;.w >.>.,.'.).).!.+ ~. .{.]. ",
" ^./.(.y _.f :.) <.[.^ }.|.).1.2.3. .4.* 5. .6.1 4.7.8.9. ",
" 0.a.b.c./ d.e.f.| g.h.9 i.* j.|.k.7.7.l.m.n.o.@.p.q.r.s. ",
" t.u.v.w.x.y.% z.A.).B.C.D.m.E.{.F.F.G.r.H.I.J.k.K.L.M.N. ",
" O.P.Q.R.S.T.U.V.W.q.X.r.Y.Z.`.Y. +`..+++{.@+#+$+++%+y. ",
" &+*+W.=+-+;+X.>+y .+K.K.y y ,+'+)+!+~+{+]+^+].$+/+$+J. ",
" (+_+:+U.$+<+[+}+/+h.=.|+1+2+3+4+5+6+7+8+9+0+_.a+/+0 b+ ",
" c+d+h.a+/+++e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+$ ",
" x+f.- y+w.z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+$ ",
" R+S+T+U+V+W+F+X+H+I+Y+Z+`+ @.@+@@@#@$@%@$ ",
"&@*@=@-@;@>@,@'@)@H+!@Y+K+~@{@]@+@^@/@(@_@:@<@[@}@|@1@2@3@ ",
"4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@",
" z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #",
" .#+#@###$#%#&#*#=#-#;#>#,#'# )#!#~#{#]#^#/#",
" (#_#:#<#",
" [#}#",
" ",
" ",
" ",
" "};
"""
def sections(obj):
""" Returns the discretization points of sections, with the advantage
that is a list of nSections lists, with the points.
@param Ship object
@return Sections points
"""
histogram = obj.nPoints[:]
points = obj.mSections[:]
sections = []
for i in range(0, len(histogram) - 1):
sections.append([])
for j in range(histogram[i],histogram[i+1]):
sections[i].append(points[j])
return sections

61
src/Mod/Ship/Makefile.am Normal file
View File

@@ -0,0 +1,61 @@
# Change data dir from default ($(prefix)/share) to actual dir
datadir = $(prefix)/Mod/Ship
data_DATA = \
InitGui.py \
ShipGui.py \
Instance.py
nobase_data_DATA = \
Icons/AreaCurveIco.png \
Icons/AreaCurveIco.xcf \
Icons/AreaCurveIco.xpm \
Icons/DataIco.png \
Icons/DataIco.xcf \
Icons/DataIco.xpm \
Icons/DiscretizeIco.png \
Icons/DiscretizeIco.xcf \
Icons/DiscretizeIco.xpm \
Icons/HydrostaticsIco.png \
Icons/HydrostaticsIco.xcf \
Icons/HydrostaticsIco.xpm \
Icons/Ico.png \
Icons/Ico.xcf \
Icons/Ico.xpm \
Icons/OutlineDrawIco.png \
Icons/OutlineDrawIco.xcf \
Icons/OutlineDrawIco.xpm \
Icons/ReparametrizeIco.png \
Icons/ReparametrizeIco.xcf \
Icons/ReparametrizeIco.xpm \
Icons/Ship.xcf \
Icons/Ship.xpm \
shipCreateShip/__init__.py \
shipCreateShip/Preview.py \
shipCreateShip/TaskPanel.py \
shipCreateShip/TaskPanel.ui \
shipOutlineDraw/__init__.py \
shipOutlineDraw/Plot.py \
shipOutlineDraw/Preview.py \
shipOutlineDraw/TaskPanel.py \
shipOutlineDraw/TaskPanel.ui \
shipAreasCurve/__init__.py \
shipAreasCurve/Preview.py \
shipAreasCurve/TaskPanel.py \
shipAreasCurve/TaskPanel.ui \
shipHydrostatics/__init__.py \
shipHydrostatics/Tools.py \
shipUtils/__init__.py \
shipUtils/Math.py \
shipUtils/Paths.py \
shipUtils/Translator.py
CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = \
$(data_DATA) \
$(nobase_data_DATA) \
CMakeLists.txt \
README \
ship.dox

10
src/Mod/Ship/README Normal file
View File

@@ -0,0 +1,10 @@
* Authors
---------
Jose Luis Cercós Pita <jlcercos@gmail.com>
* Introduction
--------------
FreeCAD-Ship is a free module for FreeCAD oriented to aid ship design providing most common tools (Outline drawing, hydrostatics, ...).

65
src/Mod/Ship/ShipGui.py Normal file
View File

@@ -0,0 +1,65 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
from PyQt4 import QtCore, QtGui
import FreeCAD, FreeCADGui, os
class CreateShip:
def Activated(self):
import shipCreateShip
shipCreateShip.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/Ico.png"
MenuText = str(Translator.translate('Create a new ship'))
ToolTip = str(Translator.translate('Create a new ship in order to work with them'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class OutlineDraw:
def Activated(self):
import shipOutlineDraw
shipOutlineDraw.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/OutlineDrawIco.png"
MenuText = str(Translator.translate('Outline draw'))
ToolTip = str(Translator.translate('Plot ship outline draw'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class AreasCurve:
def Activated(self):
import shipAreasCurve
shipAreasCurve.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/AreaCurveIco.png"
MenuText = str(Translator.translate('Areas curve'))
ToolTip = str(Translator.translate('Plot transversal areas curve'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
FreeCADGui.addCommand('Ship_CreateShip', CreateShip())
FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw())
FreeCADGui.addCommand('Ship_AreasCurve', AreasCurve())

3
src/Mod/Ship/ship.dox Normal file
View File

@@ -0,0 +1,3 @@
/** \defgroup SHIP Ship
* \ingroup WORKBENCHES */

View File

@@ -0,0 +1,78 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCADShip modules
from shipUtils import Paths, Translator
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.obj = None
self.clean()
def update(self, draft, trim, ship):
""" Update free surface 3D view
@param traft Draft.
@param trim Trim in degrees.
"""
# Destroy old object if exist
self.clean()
# Set free surface bounds
bbox = ship.Shape.BoundBox
L = 1.5 * bbox.XLength
B = 3.0 * bbox.YLength
# Create plane
x = - 0.5 * L
y = - 0.5 * B
point = Base.Vector(x,y,0.0)
plane = Part.makePlane(L,B, point, Base.Vector(0,0,1))
# Set position
plane.rotate(Base.Vector(0,0,0), Base.Vector(0,1,0), trim)
plane.translate(Base.Vector(0,0,draft))
# Create the FreeCAD object
Part.show(plane)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs)-1]
self.obj.Label = 'FreeSurface'
# Set properties of object
guiObj = FreeCADGui.ActiveDocument.getObject(self.obj.Name)
guiObj.ShapeColor = (0.4,0.8,0.85)
guiObj.Transparency = 50
def clean(self):
""" Erase all annotations from screen.
"""
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj=None

View File

@@ -0,0 +1,224 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry
from shipHydrostatics import Tools as Hydrostatics
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipAreasCurve/TaskPanel.ui"
self.preview = Preview.Preview()
self.ship = None
def accept(self):
if not self.ship:
return False
self.save()
self.preview.clean()
return True
def reject(self):
self.preview.clean()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = form.findChild(QtGui.QDoubleSpinBox, "Draft")
form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim")
form.output = form.findChild(QtGui.QTextEdit, "OutputData")
form.doc = QtGui.QTextDocument(form.output)
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
QtCore.QObject.connect(form.draft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.trim, QtCore.SIGNAL("valueChanged(double)"), self.onData)
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def initValues(self):
""" Set initial values for fields
"""
# Get objects
selObjs = Geometry.getSelectedObjs()
if not selObjs:
msg = Translator.translate("Ship instance must be selected (any object selected)\n")
App.Console.PrintError(msg)
return True
for i in range(0,len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
# Test if another ship already selected
if self.ship:
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
App.Console.PrintWarning(msg)
break
self.ship = obj
# Test if any valid ship was selected
if not self.ship:
msg = Translator.translate("Ship instance must be selected (any valid ship found at selected objects)\n")
App.Console.PrintError(msg)
return True
# Get bounds
bbox = self.ship.Shape.BoundBox
self.form.draft.setMaximum(bbox.ZMax)
self.form.draft.setMinimum(bbox.ZMin)
self.form.draft.setValue(self.ship.Draft)
# Try to use saved values
props = self.ship.PropertiesList
flag = True
try:
props.index("AreaCurveDraft")
except ValueError:
flag = False
if flag:
self.form.draft.setValue(self.ship.AreaCurveDraft)
flag = True
try:
props.index("AreaCurveTrim")
except ValueError:
flag = False
if flag:
self.form.trim.setValue(self.ship.AreaCurveTrim)
# Update GUI
self.preview.update(self.form.draft.value(), self.form.trim.value(), self.ship)
self.onUpdate()
msg = Translator.translate("Ready to work\n")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Plot transversal areas curve"))
self.form.findChild(QtGui.QLabel, "DraftLabel").setText(Translator.translate("Draft"))
self.form.findChild(QtGui.QLabel, "TrimLabel").setText(Translator.translate("Trim"))
def onData(self, value):
""" Method called when input data is changed.
@param value Changed value.
"""
if not self.ship:
return
self.onUpdate()
self.preview.update(self.form.draft.value(), self.form.trim.value(), self.ship)
def onUpdate(self):
""" Method called when update data request.
"""
if not self.ship:
return
# Calculate drafts
angle = math.radians(self.form.trim.value())
L = self.ship.Length
draftAP = self.form.draft.value() + 0.5*L*math.tan(angle)
if draftAP < 0.0:
draftAP = 0.0
draftFP = self.form.draft.value() - 0.5*L*math.tan(angle)
if draftFP < 0.0:
draftFP = 0.0
# Calculate hydrostatics involved
data = Hydrostatics.Displacement(self.ship,self.form.draft.value(),self.form.trim.value())
# Prepare the string in html format
string = 'L = %g [m]<BR>' % (self.ship.Length)
string = string + 'B = %g [m]<BR>' % (self.ship.Beam)
string = string + 'T = %g [m]<HR>' % (self.form.draft.value())
string = string + 'Trim = %g [degrees]<BR>' % (self.form.trim.value())
string = string + 'T<sub>AP</sub> = %g [m]<BR>' % (draftAP)
string = string + 'T<sub>FP</sub> = %g [m]<HR>' % (draftFP)
string = string + Translator.translate('Displacement') + ' = %g [ton]<BR>' % (data[1])
string = string + 'XCB = %g [m]' % (data[2])
# Set the document
self.form.output.setHtml(string)
def save(self):
""" Saves data into ship instance.
"""
props = self.ship.PropertiesList
try:
props.index("AreaCurveDraft")
except ValueError:
self.ship.addProperty("App::PropertyFloat","AreaCurveDraft","Ship", str(Translator.translate("Areas curve draft selected [m]")))
self.ship.AreaCurveDraft = self.form.draft.value()
try:
props.index("AreaCurveTrim")
except ValueError:
self.ship.addProperty("App::PropertyFloat","AreaCurveTrim","Ship", str(Translator.translate("Areas curve trim selected [m]")))
self.ship.AreaCurveTrim = self.form.draft.value()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>256</height>
</rect>
</property>
<property name="windowTitle">
<string>Create new ship</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="DraftLabel">
<property name="text">
<string>Draft</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Draft">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="DraftUnits">
<property name="maximumSize">
<size>
<width>24</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>m</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="TrimLabel">
<property name="text">
<string>Trim</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Trim">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-45.000000000000000</double>
</property>
<property name="maximum">
<double>45.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="TrimUnits">
<property name="maximumSize">
<size>
<width>24</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Deg</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QTextEdit" name="OutputData">
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,36 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,130 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCADShip modules
from shipUtils import Paths, Translator
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.baseLine = None
self.baseLineLabel = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.clean()
def update(self, L, B, T):
""" Update the 3D view printing annotations.
@param L Ship length.
@param B Ship beam.
@param T Ship draft.
"""
# Destroy all previous entities
self.clean()
# Draw base line
xStart = -0.6*L;
xEnd = 0.6*L;
baseLine = Part.makeLine((xStart,0,0),(xEnd,0,0))
Part.show(baseLine)
objs = FreeCAD.ActiveDocument.Objects
self.baseLine = objs[len(objs)-1]
self.baseLine.Label = 'BaseLine'
self.baseLineLabel = DrawText('BaseLineText', str(Translator.translate('Base line')), Base.Vector(xEnd,0,0))
# Draw free surface
fsLine = Part.makeLine((xStart,0,T),(xEnd,0,T))
Part.show(fsLine)
objs = FreeCAD.ActiveDocument.Objects
self.fsLine = objs[len(objs)-1]
self.fsLine.Label = 'FreeSurface'
self.fsLineLabel = DrawText('FSText', str(Translator.translate('Free surface')), Base.Vector(xEnd,0,T))
# Draw forward perpendicular
zStart = -0.1*T
zEnd = 1.1*T
fpLine = Part.makeLine((0.5*L,0,zStart),(0.5*L,0,zEnd))
Part.show(fpLine)
objs = FreeCAD.ActiveDocument.Objects
self.fpLine = objs[len(objs)-1]
self.fpLine.Label = 'ForwardPerpendicular'
self.fpLineLabel = DrawText('FPText', str(Translator.translate('Forward perpendicular')), Base.Vector(0.5*L,0,zEnd))
# Draw after perpendicular
apLine = Part.makeLine((-0.5*L,0,zStart),(-0.5*L,0,zEnd))
Part.show(apLine)
objs = FreeCAD.ActiveDocument.Objects
self.apLine = objs[len(objs)-1]
self.apLine.Label = 'AfterPerpendicular'
self.apLineLabel = DrawText('APText', str(Translator.translate('After perpendicular')), Base.Vector(-0.5*L,0,zEnd))
# Draw amin frame
amLine = Part.makeLine((0,-0.5*B,zStart),(0,-0.5*B,zEnd))
Part.show(amLine)
objs = FreeCAD.ActiveDocument.Objects
self.amLine = objs[len(objs)-1]
self.amLine.Label = 'AminFrame'
self.amLineLabel = DrawText('AMText', str(Translator.translate('Amin frame')), Base.Vector(0,-0.5*B,zEnd))
def clean(self):
""" Erase all annotations from screen.
"""
if not self.baseLine:
return
FreeCAD.ActiveDocument.removeObject(self.baseLine.Name)
FreeCAD.ActiveDocument.removeObject(self.baseLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.apLine.Name)
FreeCAD.ActiveDocument.removeObject(self.apLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.amLine.Name)
FreeCAD.ActiveDocument.removeObject(self.amLineLabel.Name)
def DrawText(name, string, position, displayMode="Screen", angle=0.0, justification="Left", colour=(0.00,0.00,0.00), size=12):
""" Draws a text in a desired position.
@param name Name of the object
@param string Text to draw (recommended format u'')
@param position Point to draw the text
@param angle Counter clockwise rotation of text
@param justification Alignement of the text ("Left", "Right" or "Center")
@param colour Colour of the text
@param size Font size
@return FreeCAD annotation object
"""
# Create the object
text = FreeCAD.ActiveDocument.addObject("App::Annotation",name)
# Set the text
text.LabelText = [string, u'']
# Set the options
text.Position = position
FreeCADGui.ActiveDocument.getObject(text.Name).Rotation = angle
FreeCADGui.ActiveDocument.getObject(text.Name).Justification = justification
FreeCADGui.ActiveDocument.getObject(text.Name).FontSize = size
FreeCADGui.ActiveDocument.getObject(text.Name).TextColor = colour
FreeCADGui.ActiveDocument.getObject(text.Name).DisplayMode = displayMode
return FreeCAD.ActiveDocument.getObject(text.Name)

View File

@@ -0,0 +1,199 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipCreateShip/TaskPanel.ui"
self.preview = Preview.Preview()
def accept(self):
self.preview.clean()
# Create new ship instance
obj = App.ActiveDocument.addObject("Part::FeaturePython","Ship")
ship = Instance.Ship(obj, self.faces)
Instance.ViewProviderShip(obj.ViewObject)
# Set main dimensions
obj.Length = self.form.length.value()
obj.Beam = self.form.beam.value()
obj.Draft = self.form.draft.value()
# Discretize it
ship.discretize(self.form.nSections.value(), self.form.nPoints.value())
return True
def reject(self):
self.preview.clean()
self.close()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
form.draft = form.findChild(QtGui.QDoubleSpinBox, "Draft")
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
form.nPoints = form.findChild(QtGui.QSpinBox, "NPoints")
form.mainLogo = form.findChild(QtGui.QLabel, "MainLogo")
iconPath = Paths.iconsPath() + "/Ico.xpm"
form.mainLogo.setPixmap(QtGui.QPixmap(iconPath))
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.preview.update(self.L, self.B, self.T)
# Connect Signals and Slots
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.draft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.nSections, QtCore.SIGNAL("valueChanged(int)"), self.onDiscretization)
QtCore.QObject.connect(form.nPoints, QtCore.SIGNAL("valueChanged(int)"), self.onDiscretization)
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def initValues(self):
""" Set initial values for fields
"""
# Get objects
self.faces = None
selObjs = Geometry.getSelectedObjs()
if not selObjs:
msg = Translator.translate("All ship surfaces must be selected (Any object has been selected)\n")
App.Console.PrintError(msg)
return True
self.faces = []
for i in range(0, len(selObjs)):
faces = Geometry.getFaces(selObjs[i])
for j in range(0, len(faces)):
self.faces.append(faces[j])
if not self.faces:
msg = Translator.translate("All ship surfaces must be selected (Any face found into selected objects)\n")
App.Console.PrintError(msg)
return True
# Get bounds
bounds = [0.0, 0.0, 0.0]
bbox = self.faces[0].BoundBox
bounds[0] = bbox.XLength
bounds[1] = bbox.YLength
bounds[2] = bbox.ZLength
for i in range(1,len(self.faces)):
bbox = self.faces[i].BoundBox
if bounds[0] < bbox.XLength:
bounds[0] = bbox.XLength
if bounds[1] < bbox.YLength:
bounds[1] = bbox.YLength
if bounds[2] < bbox.ZLength:
bounds[2] = bbox.ZLength
# Set UI fields
self.form.length.setMaximum(bounds[0])
self.form.length.setValue(bounds[0])
self.L = bounds[0]
self.form.beam.setMaximum(2.0*bounds[1])
self.form.beam.setValue(2.0*bounds[1])
self.B = 2.0*bounds[1]
self.form.draft.setMaximum(bounds[2])
self.form.draft.setValue(0.5*bounds[2])
self.T = 0.5*bounds[2]
msg = Translator.translate("Ready to work\n")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Create a new ship"))
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(Translator.translate("Length"))
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(Translator.translate("Beam"))
self.form.findChild(QtGui.QLabel, "DraftLabel").setText(Translator.translate("Draft"))
self.form.findChild(QtGui.QLabel, "NSectionsLabel").setText(Translator.translate("Number of sections"))
self.form.findChild(QtGui.QLabel, "NPointsLabel").setText(Translator.translate("Points per section"))
def onData(self, value):
""" Method called when ship data is changed.
Annotations must be showed.
@param value Changed value.
"""
self.L = self.form.length.value()
self.B = self.form.beam.value()
self.T = self.form.draft.value()
self.preview.update(self.L, self.B, self.T)
def onDiscretization(self, value):
""" Method called when discretization data is changed.
Annotations must be showed.
@param value Changed value.
"""
pass
def close(self):
""" Destroy all dependant objects
"""
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>514</height>
</rect>
</property>
<property name="windowTitle">
<string>Create new ship</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="MainLogo">
<property name="minimumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>../Icons/Ico.xpm</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="ShipDataBox">
<property name="minimumSize">
<size>
<width>240</width>
<height>160</height>
</size>
</property>
<property name="title">
<string>Ship data</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>241</width>
<height>141</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,0">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="LengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Length">
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="BeamLabel">
<property name="text">
<string>Beam</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Beam">
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="DraftLabel">
<property name="text">
<string>Draft</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Draft">
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="DiscretizationBox">
<property name="minimumSize">
<size>
<width>240</width>
<height>160</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="title">
<string>Discretization</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget_3">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>241</width>
<height>101</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NSectionsLabel">
<property name="text">
<string>Number of sections</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="NSections">
<property name="minimum">
<number>50</number>
</property>
<property name="maximum">
<number>500</number>
</property>
<property name="singleStep">
<number>50</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NPointsLabel">
<property name="text">
<string>Points per section</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="NPoints">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>500</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,36 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,104 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Module
import Instance
def Displacement(ship, draft, trim):
""" Calculate ship displacement.
@param ship Selected ship instance
@param traft Draft.
@param trim Trim in degrees.
@return [areas,disp,xcb]: \n
areas : Area of each section \n
disp: Ship displacement \n
xcb: X bouyance center coordinate
"""
angle = math.radians(trim)
sections = Instance.sections(ship)
xCoord = ship.xSection[:]
areas = []
vol = 0.0
moment = 0.0
if not sections:
return [[],0.0,0.0]
for i in range(0, len(sections)):
# Get the section
section = sections[i]
if len(section) < 2: # Empty section
areas.append(0.0)
continue
# Get the position of the section
x = xCoord[i]
# Get the maximum Z value
Z = draft - x*math.tan(angle)
# Count the number of valid points
n = 0
for j in range(0,len(section)):
z = section[j].z
if z > Z:
break
n = n+1
# Discard invalid sections
if n == 0:
areas.append(0.0)
continue
# Truncate only valid points
points = section[0:n]
# Study if additional point is needed
if n < len(section):
y0 = section[n-1].y
z0 = section[n-1].z
y1 = section[n].y
z1 = section[n].z
factor = (Z - z0) / (z1 - z0)
y = y0 + factor*(y1 - y0)
points.append(App.Base.Vector(x,y,Z))
# Integrate area
area = 0.0
for j in range(0, len(points)-1):
y0 = abs(points[j].y)
z0 = points[j].z
y1 = abs(points[j+1].y)
z1 = points[j+1].z
y = 0.5 * (y0 + y1)
dz = z1 - z0
area = area + 2.0*y*dz # 2x because only half ship is represented
areas.append(area)
# Add volume & moment if proceed
if i > 0:
dx = xCoord[i] - xCoord[i-1]
x = 0.5*(xCoord[i] + xCoord[i-1])
area = 0.5*(areas[i] + areas[i-1])
vol = vol + area*dx
moment = moment + area*dx*x
# Compute displacement and xcb
disp = vol / 1.025 # rho = 1.025 ton/m3 (salt water density)
xcb = 0.0
if vol > 0.0:
xcb = moment / vol
return [areas,disp,xcb]

View File

@@ -0,0 +1,23 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************

View File

@@ -0,0 +1,95 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base, Part, Vector
# FreeCADShip modules
from shipUtils import Paths, Translator
from surfUtils import Geometry
def Plot(scale, sections, shape):
""" Creates the outline draw.
@param scale Plane scale (format 1:scale)
@param sections Sections computed.
@param shape Ship surfaces shell
@return plotted object (DocumentObject)
"""
msg = Translator.translate('Performing plot (Scale 1:%d)...\n' % (scale))
FreeCAD.Console.PrintMessage(msg)
scale = 1000.0 / scale
# Take positions
bounds = [0.0, 0.0, 0.0]
bbox = shape.BoundBox
bounds[0] = bbox.XLength
bounds[1] = bbox.YLength
bounds[2] = bbox.ZLength
xTot = scale*bounds[1] + 32.0 + scale*bounds[0]
yTot = scale*bounds[2] + 32.0 + scale*bounds[1]
xMid = 210.0
yMid = 185.0
x0 = xMid - 0.5*xTot
y0 = 297.0 - yMid - 0.5*yTot # 297 = A3_width
# Get border
edges = Geometry.getEdges([shape])
border = edges[0]
for i in range(0,len(edges)):
border = border.oldFuse(edges[i]) # Only group objects, don't try to build more complex entities
border = border.oldFuse(edges[i].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0)))
# Fuse sections & borders
obj = sections.oldFuse(border)
# Send to 3D view
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
obj = objs[len(objs)-1]
# Create a new plane
FreeCAD.ActiveDocument.addObject('Drawing::FeaturePage','OutlineDrawPlot')
FreeCAD.ActiveDocument.OutlineDrawPlot.Template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg'
# Side view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawSideView')
FreeCAD.ActiveDocument.OutlineDrawSideView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawSideView.Direction = (1.0,0.0,0.0)
FreeCAD.ActiveDocument.OutlineDrawSideView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawSideView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawSideView.X = 420.0 - x0 - 0.5*scale*bounds[1] # 420 = A3_height
FreeCAD.ActiveDocument.OutlineDrawSideView.Y = y0 + 0.5*scale*bounds[2]
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawSideView)
# Front view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawFrontView')
FreeCAD.ActiveDocument.OutlineDrawFrontView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawFrontView.Direction = (0.0,1.0,0.0)
FreeCAD.ActiveDocument.OutlineDrawFrontView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawFrontView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawFrontView.X = 420.0 - x0 - scale*bounds[1] - 32 - 0.5*scale*bounds[0]
FreeCAD.ActiveDocument.OutlineDrawFrontView.Y = y0 + 0.5*scale*bounds[2]
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawFrontView)
# Up view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawUpView')
FreeCAD.ActiveDocument.OutlineDrawUpView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawUpView.Direction = (0.0,0.0,1.0)
FreeCAD.ActiveDocument.OutlineDrawUpView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawUpView.X = 420.0 - x0 - scale*bounds[1] - 32 - 0.5*scale*bounds[0]
FreeCAD.ActiveDocument.OutlineDrawUpView.Y = y0 + scale*bounds[2] + 32
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawUpView)
FreeCAD.ActiveDocument.recompute()
return obj

View File

@@ -0,0 +1,126 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base, Part, Vector
# FreeCADShip modules
from shipUtils import Paths, Translator
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.obj = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.clean()
def update(self, L, B, T, sectionsL, sectionsB, sectionsT, shape):
""" Update the 3D view printing annotations.
@param L Ship Lpp.
@param B Ship beam.
@param T Ship draft.
@param sectionsL Transversal sections.
@param sectionsB Longitudinal sections.
@param sectionsT Water lines.
@param shape Ship surfaces shell
@return Sections object. None if errors happens.
"""
FreeCAD.Console.PrintMessage(Translator.translate('Computing sections...\n'))
# Destroy all previous entities
self.clean()
# Receive data
nL = len(sectionsL)
nB = len(sectionsB)
nT = len(sectionsT)
if not (nL or nB or nT):
return None
# Found sections
sections = []
for i in range(0,nL):
pos = sectionsL[i]
section = shape.slice(Vector(1.0,0.0,0.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
if pos == 0.0:
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges2 = section[j].Edges
for k in range(0,len(edges2)):
edges.append(edges2[k])
elif pos < 0:
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges = section[j].Edges
for k in range(0,len(edges)):
sections.append(edges[k])
for i in range(0,nB):
pos = sectionsB[i]
section = shape.slice(Vector(0.0,1.0,0.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges2 = section[j].Edges
for k in range(0,len(edges2)):
edges.append(edges2[k])
for k in range(0,len(edges)):
sections.append(edges[k])
for i in range(0,nT):
pos = sectionsT[i]
section = shape.slice(Vector(0.0,0.0,1.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
if pos == T:
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges2 = section[j].Edges
for k in range(0,len(edges2)):
edges.append(edges2[k])
elif pos > T:
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges = section[j].Edges
for k in range(0,len(edges)):
sections.append(edges[k])
# Convert all BSplines into a shape
if not sections:
msg = Translator.translate('Any valid ship section found\n')
FreeCAD.Console.PrintWarning(msg)
return
obj = sections[0]
for i in range(1,len(sections)):
obj = obj.oldFuse(sections[i]) # Only group the edges, don't try to build more complex entities
# Create the representable object
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs)-1]
self.obj.Label = 'OutlineDraw'
return self.obj
def clean(self):
""" Erase all annotations from screen.
"""
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj = None

View File

@@ -0,0 +1,349 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview, Plot
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
self.ship = None
self.skip = False
self.LSections = []
self.BSections = []
self.TSections = []
self.obj = None
self.preview = Preview.Preview()
def accept(self):
self.saveSections()
self.obj = Plot.Plot(self.form.scale.value(), self.obj.Shape, self.ship.Shape)
self.preview.clean()
self.obj.Label = 'OutlineDraw'
return True
def reject(self):
self.preview.clean()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = form.findChild(QtGui.QTableWidget, "Sections")
try:
form.sections.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly)
except:
msg = Translator.translate("QtCore.Qt.ImhFormattedNumbersOnly not supported, will not used.\n")
App.Console.PrintWarning(msg)
form.sectionType = form.findChild(QtGui.QComboBox, "SectionType")
form.deleteButton = form.findChild(QtGui.QPushButton, "DeleteButton")
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
form.createButton = form.findChild(QtGui.QPushButton, "CreateButton")
form.scale = form.findChild(QtGui.QSpinBox, "Scale")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
# Connect Signals and Slots
QtCore.QObject.connect(form.sectionType,QtCore.SIGNAL("activated(QString)"),self.onSectionType)
QtCore.QObject.connect(form.sections,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem);
QtCore.QObject.connect(form.deleteButton,QtCore.SIGNAL("pressed()"),self.onDeleteButton)
QtCore.QObject.connect(form.createButton,QtCore.SIGNAL("pressed()"),self.onCreateButton)
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def initValues(self):
""" Set initial values for fields
"""
# Get selected objects
selObjs = Geometry.getSelectedObjs()
if not selObjs:
msg = Translator.translate("Ship instance must be selected (any object selected)\n")
App.Console.PrintError(msg)
return True
for i in range(0,len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
# Test if another ship already selected
if self.ship:
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
App.Console.PrintWarning(msg)
break
self.ship = obj
# Test if any valid ship was selected
if not self.ship:
msg = Translator.translate("Ship instance must be selected (any valid ship found at selected objects)\n")
App.Console.PrintError(msg)
return True
# Load sections (if exist)
self.loadSections()
msg = Translator.translate("Ready to work\n")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Outline draw"))
self.form.findChild(QtGui.QGroupBox, "AutoCreateBox").setTitle(Translator.translate("Auto create"))
self.form.findChild(QtGui.QGroupBox, "ScaleBox").setTitle(Translator.translate("Scale"))
self.form.findChild(QtGui.QPushButton, "DeleteButton").setText(Translator.translate("Delete all sections"))
self.form.findChild(QtGui.QPushButton, "CreateButton").setText(Translator.translate("Create sections"))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(0, Translator.translate("Transversal"))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(1, Translator.translate("Longitudinal"))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(2, Translator.translate("Water lines"))
def onSectionType(self):
""" Function called when the section type is changed.
"""
# Search section type
ID = self.form.sectionType.currentIndex()
self.setSectionType(ID)
def setSectionType(self, ID):
""" Function that set the type section related table.
@param ID Id of the section to set: \n
0 = Transversal sections \n
1 = Longitudinal sections \n
2 = Water lines
"""
SectionList = []
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
nRow = len(SectionList)
self.form.sections.clearContents()
self.form.sections.setRowCount(nRow+1)
if not nRow:
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
return
self.skip = True # Avoid recursive call to OnItem
for i in range(0,nRow):
if i == nRow-1:
self.skip = False
string = '%f' % (SectionList[i])
item = QtGui.QTableWidgetItem(string)
self.form.sections.setItem(i,0,item)
def onTableItem(self, row, column):
""" Function called when an item of table is changed.
@param row Changed item row
@param column Changed item column
"""
if self.skip:
return
# Ensure that exist one empty item at least
nRow = self.form.sections.rowCount()
item = self.form.sections.item(nRow-1,0)
if item :
if(item.text() != ''):
self.form.sections.setRowCount(nRow+1)
# Ensure that new item is a number
ID = self.form.sectionType.currentIndex()
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
item = self.form.sections.item(row,column)
(number,flag) = item.text().toFloat()
if not flag:
if len(SectionList) > nRow-1:
number = SectionList[nRow-1]
else:
number = 0.0
string = '%f' % (number)
item.setText(string)
# Regenerate the list
SectionList = []
for i in range(0,nRow):
item = self.form.sections.item(i,0)
if item:
(number,flag) = item.text().toFloat()
SectionList.append(number)
# Paste it into the class list
ID = self.form.sectionType.currentIndex()
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
def onDeleteButton(self):
""" Function called when the delete button is pressed.
All sections mustt be erased
"""
self.form.sections.clearContents()
self.form.sections.setRowCount(1)
# Clear active list
ID = self.form.sectionType.currentIndex()
if ID == 0:
self.LSections = []
elif ID == 1:
self.BSections = []
elif ID == 2:
self.TSections = []
self.setSectionType(ID)
def onCreateButton(self):
""" Function called when create button is pressed.
Several sections must be added to list
"""
# Recolect data
nSections = self.form.nSections.value()
SectionList = []
L = 0.0
ID = self.form.sectionType.currentIndex()
if ID == 0:
L = self.ship.Length
d = L / (nSections-1) # Distance between sections
start = - L/2.0 # Ship must have 0.0 at coordinates origin
elif ID == 1:
L = -0.5*self.ship.Beam # Ship must be in y<0.0
d = L / (nSections+1.0) # Distance between sections
start = d
elif ID == 2:
L = self.ship.Draft
d = L / (nSections) # Distance between sections
start = d
# Calculate sections
for i in range(0,nSections):
sec = i*d + start
SectionList.append(sec)
# Paste into class table
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
# Print the table
self.setSectionType(ID)
def loadSections(self):
""" Loads from ship object previously selected sections.
"""
# Load sections
props = self.ship.PropertiesList
flag=True
try:
props.index("LSections")
except ValueError:
flag=False
if flag:
self.LSections = self.ship.LSections[:]
self.BSections = self.ship.BSections[:]
self.TSections = self.ship.TSections[:]
# Load scale too
flag=True
try:
props.index("PlotScale")
except ValueError:
flag=False
if flag:
self.form.scale.setValue(self.ship.PlotScale)
# Set UI
self.setSectionType(self.form.sectionType.currentIndex())
def saveSections(self):
""" Save selected sections into ship object.
"""
# Test if previous section have been created
props = self.ship.PropertiesList
try:
props.index("LSections")
except ValueError:
# Create new sections list
self.ship.addProperty("App::PropertyFloatList","LSections","Ship", str(Translator.translate("Transversal sections position [m]"))).LSections=[]
self.ship.addProperty("App::PropertyFloatList","BSections","Ship", str(Translator.translate("Longitudinal sections position [m]"))).BSections=[]
self.ship.addProperty("App::PropertyFloatList","TSections","Ship", str(Translator.translate("Water lines position [m]"))).TSections=[]
# Save sections
self.ship.LSections = self.LSections[:]
self.ship.BSections = self.BSections[:]
self.ship.TSections = self.TSections[:]
# Save also scale
try:
props.index("PlotScale")
except ValueError:
self.ship.addProperty("App::PropertyInteger","PlotScale","Ship", str(Translator.translate("Plot scale (1:scale format)"))).PlotScale=250
self.ship.PlotScale = self.form.scale.value()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>298</width>
<height>402</height>
</rect>
</property>
<property name="windowTitle">
<string>Outline draw</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QComboBox" name="SectionType">
<property name="minimumSize">
<size>
<width>142</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>32</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="minimumContentsLength">
<number>0</number>
</property>
<item>
<property name="text">
<string>Transversal</string>
</property>
</item>
<item>
<property name="text">
<string>Longitudinal</string>
</property>
</item>
<item>
<property name="text">
<string>Water lines</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="DeleteButton">
<property name="minimumSize">
<size>
<width>142</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>32</height>
</size>
</property>
<property name="text">
<string>Delete all sections</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="AutoCreateBox">
<property name="minimumSize">
<size>
<width>142</width>
<height>256</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>350</height>
</size>
</property>
<property name="title">
<string>Auto create</string>
</property>
<widget class="QSpinBox" name="NSections">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>142</width>
<height>27</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>142</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>32</height>
</size>
</property>
</widget>
<widget class="QPushButton" name="CreateButton">
<property name="geometry">
<rect>
<x>0</x>
<y>70</y>
<width>142</width>
<height>27</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>142</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>32</height>
</size>
</property>
<property name="text">
<string>Create sections</string>
</property>
</widget>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QTableWidget" name="Sections">
<property name="minimumSize">
<size>
<width>128</width>
<height>256</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>16777215</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="rowCount">
<number>1</number>
</property>
<property name="columnCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>true</bool>
</attribute>
<row/>
<column/>
</widget>
</item>
</layout>
</item>
<item row="1" column="1" colspan="2">
<widget class="QGroupBox" name="ScaleBox">
<property name="minimumSize">
<size>
<width>128</width>
<height>72</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>256</width>
<height>96</height>
</size>
</property>
<property name="title">
<string>Plane scale</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>251</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="ScaleLabel">
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>1:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Scale">
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="singleStep">
<number>50</number>
</property>
<property name="value">
<number>250</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,36 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,57 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
def isAprox(a,b,tol=0.0001):
"""returns if a value is into (b-tol,b+tol)
@param a Value to compare.
@param b Center of valid interval
@param tol Radius of valid interval
@return True if a is into (b-tol,b+tol), False otherwise
"""
if (a < b+abs(tol)) and (a > b-abs(tol)):
return True
return False
def isSamePoint(a,b,tol=0.0001):
"""returns if two points are the same with a provided tolerance
@param a Point to compare.
@param b Reference point.
@param tol Radius of valid interval
@return True if twice point are the same, False otherwise
@note FreeCAD::Base::Vector types must be provided
"""
if isAprox(a.x,b.x,tol) and isAprox(a.y,b.y,tol) and isAprox(a.z,b.z,tol):
return True
return False
def isSameVertex(a,b,tol=0.0001):
"""returns if two points are the same with a provided tolerance
@param a Point to compare.
@param b Reference point.
@param tol Radius of valid interval
@return True if twice point are the same, False otherwise
@note FreeCAD::Part::Vertex types must be provided
"""
if isAprox(a.X,b.X,tol) and isAprox(a.Y,b.Y,tol) and isAprox(a.Z,b.Z,tol):
return True
return False

View File

@@ -0,0 +1,55 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD, FreeCADGui, os
def modulePath():
"""returns the current Ship design module path
@return Module path"""
path1 = FreeCAD.ConfigGet("AppHomePath") + "Mod/Ship"
path2 = FreeCAD.ConfigGet("UserAppData") + "Mod/Ship"
if os.path.exists(path2):
return path2
else:
return path1
def iconsPath():
"""returns the current Ship design module icons path
@return Icons path"""
path = modulePath() + "/Icons"
return path
def getPathFromFile(fileName):
""" Gets the directory path from a file name
@param fileName Name of the file
@return Directory path.
"""
if not fileName:
return ''
i = 1
try:
while 1:
i = fileName.index("/", i+1)
except ValueError:
pass
return fileName[0:i+1]

View File

@@ -0,0 +1,30 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD, FreeCADGui, os
from PyQt4 import QtCore,QtGui
def translate(text,context="ship"):
"convenience function for Qt translator"
return QtGui.QApplication.translate(context, text, None,
QtGui.QApplication.UnicodeUTF8)

View File

@@ -0,0 +1,25 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# Empty file to treat the folder as a package

View File

@@ -0,0 +1,116 @@
SET(SurfMain_SRCS
InitGui.py
SurfGui.py
)
SOURCE_GROUP("" FILES ${SurfMain_SRCS})
SET(SurfIcons_SRCS
Icons/BorderIco.png
Icons/BorderIco.xpm
Icons/ConvertIco.png
Icons/ConvertTo4SidesIco.xpm
Icons/Ico.xcf
Icons/IsoCurveIco.png
Icons/IsoCurveIco.xpm
Icons/SliceIco.xcf
Icons/BorderIco.xcf
Icons/ConvertIco.xcf
Icons/Ico.png
Icons/Ico.xpm
Icons/IsoCurveIco.xcf
Icons/SliceIco.png
Icons/SliceIco.xpm
)
SOURCE_GROUP("surficons" FILES ${SurfIcons_SRCS})
SET(SurfBorder_SRCS
surfBorder/__init__.py
)
SOURCE_GROUP("surfborder" FILES ${SurfBorder_SRCS})
SET(SurfConvert_SRCS
surfConvert/__init__.py
surfConvert/Preview.py
surfConvert/TaskPanel.py
surfConvert/TaskPanel.ui
)
SOURCE_GROUP("surfconvert" FILES ${SurfConvert_SRCS})
SET(SurfISOCurve_SRCS
surfISOCurve/__init__.py
surfISOCurve/PointTracker.py
surfISOCurve/TaskPanel.py
surfISOCurve/Preview.py
surfISOCurve/TaskPanel.ui
)
SOURCE_GROUP("surfISOcurve" FILES ${SurfISOCurve_SRCS})
SET(SurfSlice_SRCS
surfSlice/__init__.py
surfSlice/PointTracker.py
surfSlice/TaskPanel.py
surfSlice/Preview.py
surfSlice/TaskPanel.ui
)
SOURCE_GROUP("surfslice" FILES ${SurfSlice_SRCS})
SET(SurfUtils_SRCS
surfUtils/__init__.py
surfUtils/Geometry.py
surfUtils/Math.py
surfUtils/Paths.py
surfUtils/Translator.py
)
SOURCE_GROUP("surfutils" FILES ${SurfUtils_SRCS})
SET(all_files ${SurfMain_SRCS} ${SurfIcons_SRCS} ${SurfBorder_SRCS} ${SurfConvert_SRCS} ${SurfISOCurve_SRCS} ${SurfSlice_SRCS} ${SurfUtils_SRCS})
ADD_CUSTOM_TARGET(Surfaces ALL
SOURCES ${all_files}
)
fc_copy_sources("Mod/Surfaces" "Surfaces" ${all_files})
INSTALL(
FILES
${SurfIcons_SRCS}
DESTINATION
Mod/Surfaces/Icons
)
INSTALL(
FILES
${SurfBorder_SRCS}
DESTINATION
Mod/Surfaces/surfBorder
)
INSTALL(
FILES
${SurfConvert_SRCS}
DESTINATION
Mod/Surfaces/surfConvert
)
INSTALL(
FILES
${SurfISOCurve_SRCS}
DESTINATION
Mod/Surfaces/surfISOCurve
)
INSTALL(
FILES
${SurfSlice_SRCS}
DESTINATION
Mod/Surfaces/surfSlice
)
INSTALL(
FILES
${SurfUtils_SRCS}
DESTINATION
Mod/Surfaces/surfUtils
)
INSTALL(
FILES
${SurfMain_SRCS}
DESTINATION
Mod/Surfaces
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

View File

@@ -0,0 +1,749 @@
/* XPM */
static char * Ico_xpm[] = {
"128 128 618 2",
" c None",
". c #EDECEB",
"+ c #EFEEEE",
"@ c #ECEDEC",
"# c #EFEFEF",
"$ c #000000",
"% c #EAEAEB",
"& c #EBEBEA",
"* c #E8E8E8",
"= c #E1E1E1",
"- c #DBDBDB",
"; c #D7D6D6",
"> c #E6E5E6",
", c #E9E8E8",
"' c #EEEEED",
") c #ECECEC",
"! c #EBEBEB",
"~ c #E9E9E9",
"{ c #E9E9E8",
"] c #E5E6E6",
"^ c #D7D7D7",
"/ c #B2B2B1",
"( c #A6A6A6",
"_ c #B7B7B7",
": c #D1D0D1",
"< c #ECEBEB",
"[ c #00B5AA",
"} c #00B4A8",
"| c #00B3A8",
"1 c #00B1A8",
"2 c #00B0A6",
"3 c #00AFA5",
"4 c #00AEA4",
"5 c #00ACA2",
"6 c #00ABA1",
"7 c #00AAA0",
"8 c #EAEBEA",
"9 c #E2E2E2",
"0 c #B6B6B6",
"a c #979898",
"b c #999999",
"c c #BCBCBC",
"d c #D8D9D8",
"e c #EFF0EF",
"f c #00BDB2",
"g c #00BCB1",
"h c #00BBAF",
"i c #00B9AF",
"j c #00B8AE",
"k c #00B7AC",
"l c #00B6AB",
"m c #00B4AA",
"n c #00B1A7",
"o c #00AFA4",
"p c #00ADA3",
"q c #00A99F",
"r c #00A79E",
"s c #00A79C",
"t c #00A59B",
"u c #E3E3E2",
"v c #B0B1B0",
"w c #999898",
"x c #949495",
"y c #00C2B7",
"z c #00C1B6",
"A c #00C0B5",
"B c #00BFB4",
"C c #00BDB3",
"D c #00BDB1",
"E c #00BBB0",
"F c #00BAAF",
"G c #00B9AE",
"H c #00B8AD",
"I c #00B6AC",
"J c #00B4A9",
"K c #00AEA3",
"L c #00A79D",
"M c #00A69B",
"N c #00A49A",
"O c #D7D8D7",
"P c #959696",
"Q c #A0A1A1",
"R c #DFDFE0",
"S c #00C3B8",
"T c #00C4B8",
"U c #00C2B8",
"V c #00C1B7",
"W c #00C0B4",
"X c #00BEB4",
"Y c #00BAAE",
"Z c #00B7AB",
"` c #00B0A5",
" . c #00AEA5",
".. c #00ABA2",
"+. c #00A99E",
"@. c #00A89E",
"#. c #00A69C",
"$. c #00A59A",
"%. c #00A399",
"&. c #00A298",
"*. c #EAEAEA",
"=. c #C6C5C5",
"-. c #9C9B9B",
";. c #9A9A9A",
">. c #959495",
",. c #B5B6B6",
"'. c #E6E6E6",
"). c #00C5B9",
"!. c #00BEB3",
"~. c #00B5A9",
"{. c #00B2A7",
"]. c #00B1A6",
"^. c #00A098",
"/. c #DADBDB",
"(. c #A8A8A8",
"_. c #9B9A9A",
":. c #989898",
"<. c #9E9F9F",
"[. c #D8D8D8",
"}. c #E5E5E5",
"|. c #00C3B7",
"1. c #00C6BA",
"2. c #00C6B9",
"3. c #00C5BA",
"4. c #00C5B8",
"5. c #00BCB2",
"6. c #00BCB0",
"7. c #00B8AC",
"8. c #00B3A9",
"9. c #00ADA2",
"0. c #00A398",
"a. c #00A198",
"b. c #00A097",
"c. c #B6B5B5",
"d. c #989998",
"e. c #9C9D9C",
"f. c #959596",
"g. c #BDBDBD",
"h. c #00C2B6",
"i. c #00C7BB",
"j. c #00C8BB",
"k. c #00C6BB",
"l. c #00C4B9",
"m. c #00BFB3",
"n. c #00B7AD",
"o. c #00ACA1",
"p. c #00A59C",
"q. c #00A49B",
"r. c #009E96",
"s. c #E4E4E4",
"t. c #BABBBA",
"u. c #9C9C9C",
"v. c #9E9E9E",
"w. c #9B9B9C",
"x. c #AAAAAA",
"y. c #DCDCDB",
"z. c #00C1B5",
"A. c #00C8BD",
"B. c #00C9BD",
"C. c #00C9BC",
"D. c #00C8BC",
"E. c #00B2A8",
"F. c #00AFA6",
"G. c #00A197",
"H. c #009F96",
"I. c #E4E5E4",
"J. c #B9B9B8",
"K. c #A0A09F",
"L. c #9D9D9D",
"M. c #9F9F9F",
"N. c #D8D8D9",
"O. c #00C7BA",
"P. c #00CABE",
"Q. c #00CBBF",
"R. c #00CBBE",
"S. c #00C9BE",
"T. c #00C7BC",
"U. c #00BBB1",
"V. c #00BAB0",
"W. c #00AAA1",
"X. c #00A89D",
"Y. c #13A79E",
"Z. c #03A097",
"`. c #009D94",
" + c #9F9FA0",
".+ c #A2A1A1",
"++ c #A0A0A0",
"@+ c #D0D0D0",
"#+ c #00C0B6",
"$+ c #00CCC0",
"%+ c #00CABD",
"&+ c #26ABA4",
"*+ c #10A39C",
"=+ c #009E94",
"-+ c #AEAEAE",
";+ c #A1A1A2",
">+ c #A2A3A2",
",+ c #A0A1A0",
"'+ c #D2D2D3",
")+ c #00CABF",
"!+ c #00CEC1",
"~+ c #00CDC2",
"{+ c #00CDC1",
"]+ c #00CBC0",
"^+ c #00ABA0",
"/+ c #00A9A0",
"(+ c #46B5AF",
"_+ c #63BCB6",
":+ c #009E95",
"<+ c #009C93",
"[+ c #009A92",
"}+ c #D3D3D4",
"|+ c #A8A7A7",
"1+ c #A5A4A4",
"2+ c #A4A5A5",
"3+ c #A2A2A2",
"4+ c #A3A3A2",
"5+ c #D7D7D6",
"6+ c #00CFC2",
"7+ c #00A69D",
"8+ c #0BA59B",
"9+ c #9DCAC7",
"0+ c #2DAAA2",
"a+ c #BABABA",
"b+ c #A7A7A7",
"c+ c #A6A7A6",
"d+ c #A5A6A6",
"e+ c #A3A3A3",
"f+ c #DEDEDE",
"g+ c #00CEC2",
"h+ c #00BEB2",
"i+ c #00ADA4",
"j+ c #00A39A",
"k+ c #06A29A",
"l+ c #9FCBC8",
"m+ c #8FC4C1",
"n+ c #17A39B",
"o+ c #009B92",
"p+ c #009990",
"q+ c #CACACA",
"r+ c #AEAEAD",
"s+ c #A9A9A9",
"t+ c #A8A9A8",
"u+ c #A4A4A4",
"v+ c #B6B5B6",
"w+ c #00CCBF",
"x+ c #47B2AC",
"y+ c #CCD3D4",
"z+ c #9EC8C5",
"A+ c #16A19A",
"B+ c #00988F",
"C+ c #DEDDDD",
"D+ c #AFAEAF",
"E+ c #ABACAC",
"F+ c #ACACAB",
"G+ c #A9A8A8",
"H+ c #A7A6A6",
"I+ c #CDCDCE",
"J+ c #23A9A1",
"K+ c #B5CFCE",
"L+ c #D6D6D6",
"M+ c #BFD0CE",
"N+ c #93C6C3",
"O+ c #3FABA5",
"P+ c #1C1D1D",
"Q+ c #1D1D1D",
"R+ c #292929",
"S+ c #DBDBDA",
"T+ c #DADADA",
"U+ c #C7C6C7",
"V+ c #ADADAD",
"W+ c #AEAEAF",
"X+ c #ACACAC",
"Y+ c #ACABAB",
"Z+ c #ABABAB",
"`+ c #A9AAA9",
" @ c #A5A5A6",
".@ c #D0D0CF",
"+@ c #00B9AD",
"@@ c #00B6AA",
"#@ c #019F95",
"$@ c #56B4AE",
"%@ c #C5D0D0",
"&@ c #D1D2D2",
"*@ c #CDCDCD",
"=@ c #D2D2D2",
"-@ c #D0D2D2",
";@ c #C0C0C0",
">@ c #D3D3D2",
",@ c #CBCCCC",
"'@ c #BEBFBE",
")@ c #B0AFB0",
"!@ c #B1B1B0",
"~@ c #B0B0AF",
"{@ c #ABAAAB",
"]@ c #AAAAAB",
"^@ c #A6A5A5",
"/@ c #B5B5B5",
"(@ c #D0D1D0",
"_@ c #D5D6D5",
":@ c #009F95",
"<@ c #049D95",
"[@ c #73BAB7",
"}@ c #CCD1D1",
"|@ c #C8C8C9",
"1@ c #C2C2C2",
"2@ c #C2C3C3",
"3@ c #C1C1C1",
"4@ c #B8B8B8",
"5@ c #B4B4B4",
"6@ c #B4B4B5",
"7@ c #B3B3B3",
"8@ c #B2B2B2",
"9@ c #B1B1B1",
"0@ c #AFAEAE",
"a@ c #ADAEAE",
"b@ c #ACACAD",
"c@ c #AAA9A9",
"d@ c #BBBCBC",
"e@ c #D1D1D1",
"f@ c #00B0A7",
"g@ c #00A89F",
"h@ c #059C94",
"i@ c #7ABEB9",
"j@ c #BDCCCC",
"k@ c #CBCACB",
"l@ c #C2C1C1",
"m@ c #BBBBBB",
"n@ c #B8B9B8",
"o@ c #B8B9B9",
"p@ c #B4B5B5",
"q@ c #B3B4B4",
"r@ c #B2B3B3",
"s@ c #B0B0B0",
"t@ c #AFAFAF",
"u@ c #AAA9AA",
"v@ c #D3D3D3",
"w@ c #00A096",
"x@ c #059B92",
"y@ c #29A69E",
"z@ c #ACC8C7",
"A@ c #D2D1D1",
"B@ c #CCCCCD",
"C@ c #C4C4C4",
"D@ c #C0BFBF",
"E@ c #BBBCBB",
"F@ c #B2B3B2",
"G@ c #AEADAD",
"H@ c #ADACAD",
"I@ c #00ACA3",
"J@ c #009D93",
"K@ c #009B91",
"L@ c #00968E",
"M@ c #3CA7A1",
"N@ c #8EBFBD",
"O@ c #BDCCCB",
"P@ c #C1C0C0",
"Q@ c #C4C3C3",
"R@ c #C6C6C6",
"S@ c #BAB9B9",
"T@ c #ADACAC",
"U@ c #C8C8C8",
"V@ c #020B0A",
"W@ c #00B5AB",
"X@ c #00A299",
"Y@ c #009A91",
"Z@ c #00978E",
"`@ c #00958C",
" # c #04958D",
".# c #1B9B93",
"+# c #353535",
"@# c #414141",
"## c #464646",
"$# c #CECECE",
"%# c #C4C4C3",
"&# c #B1B2B1",
"*# c #C9C9C9",
"=# c #00BFB5",
"-# c #009C94",
";# c #009B93",
"># c #00968D",
",# c #00958B",
"'# c #00938A",
")# c #009189",
"!# c #009088",
"~# c #CCCCCC",
"{# c #B1B2B2",
"]# c #ADAEAD",
"^# c #CBCCCB",
"/# c #009890",
"(# c #00958D",
"_# c #00948B",
":# c #009289",
"<# c #009188",
"[# c #BFBFBF",
"}# c #CCCBCB",
"|# c #CFCFCE",
"1# c #00948A",
"2# c #008F88",
"3# c #008E86",
"4# c #CDCECE",
"5# c #BEBEBE",
"6# c #B7B7B8",
"7# c #B6B6B5",
"8# c #B3B2B2",
"9# c #B1B0B0",
"0# c #AFAFB0",
"a# c #00998F",
"b# c #00988E",
"c# c #00948C",
"d# c #008F87",
"e# c #B9B8B9",
"f# c #B6B7B6",
"g# c #B4B3B3",
"h# c #B2B1B1",
"i# c #ADADAE",
"j# c #ACADAD",
"k# c #C0C1C0",
"l# c #008D86",
"m# c #008C84",
"n# c #C3C4C4",
"o# c #B9BAB9",
"p# c #B0B0B1",
"q# c #CBCBC9",
"r# c #00AA9F",
"s# c #00928A",
"t# c #008D85",
"u# c #008B83",
"v# c #B7B8B7",
"w# c #B7B7B6",
"x# c #B1B0B1",
"y# c #C5C5C5",
"z# c #00968C",
"A# c #C5C6C6",
"B# c #C0C1C1",
"C# c #BABBBB",
"D# c #BABAB9",
"E# c #B8B7B7",
"F# c #B7B6B7",
"G# c #B5B4B4",
"H# c #B3B2B3",
"I# c #B1B1B2",
"J# c #ACADAE",
"K# c #009F97",
"L# c #009991",
"M# c #009389",
"N# c #008F86",
"O# c #008E85",
"P# c #008B84",
"Q# c #008981",
"R# c #BCBBBC",
"S# c #B9B9B9",
"T# c #B8B8B9",
"U# c #00938B",
"V# c #008D84",
"W# c #008C83",
"X# c #008A82",
"Y# c #008880",
"Z# c #C4C3C4",
"`# c #B7B8B8",
" $ c #AFAFB1",
".$ c #00A499",
"+$ c #008B82",
"@$ c #00877F",
"#$ c #C1C2C1",
"$$ c #B9B8B8",
"%$ c #B5B5B4",
"&$ c #B4B4B3",
"*$ c #B2B1B3",
"=$ c #009087",
"-$ c #008780",
";$ c #00867E",
">$ c #C2C3C2",
",$ c #B9B9BA",
"'$ c #B2B1B2",
")$ c #008A81",
"!$ c #00867D",
"~$ c #C0C0C1",
"{$ c #BFBEBE",
"]$ c #BEBDBD",
"^$ c #BDBCBD",
"/$ c #BFC0C0",
"($ c #C1C3C2",
"_$ c #009C92",
":$ c #009288",
"<$ c #00847D",
"[$ c #00847B",
"}$ c #BBBBBC",
"|$ c #BAB9BA",
"1$ c #B6B6B7",
"2$ c #B3B3B2",
"3$ c #BFC0BF",
"4$ c #008982",
"5$ c #00857E",
"6$ c #00847C",
"7$ c #00837B",
"8$ c #BEBEBF",
"9$ c #BDBCBC",
"0$ c #BCBCBB",
"a$ c #B3B4B3",
"b$ c #00877E",
"c$ c #00857D",
"d$ c #00837C",
"e$ c #00827A",
"f$ c #B7B6B6",
"g$ c #00978D",
"h$ c #00837A",
"i$ c #008178",
"j$ c #BFBFBE",
"k$ c #BDBEBC",
"l$ c #00978F",
"m$ c #008980",
"n$ c #008179",
"o$ c #007F78",
"p$ c #C1C1C2",
"q$ c #008E87",
"r$ c #00817A",
"s$ c #C2C2C1",
"t$ c #C0BFC0",
"u$ c #BDBEBE",
"v$ c #BBBBBA",
"w$ c #B9BABA",
"x$ c #009D95",
"y$ c #00867F",
"z$ c #008078",
"A$ c #007E78",
"B$ c #007D76",
"C$ c #C3C3C3",
"D$ c #BBBABA",
"E$ c #009A90",
"F$ c #008279",
"G$ c #007E77",
"H$ c #007D75",
"I$ c #C0C0BF",
"J$ c #BFBEBF",
"K$ c #BBBABB",
"L$ c #00887F",
"M$ c #00827B",
"N$ c #008079",
"O$ c #007B75",
"P$ c #BABABB",
"Q$ c #007C75",
"R$ c #007B73",
"S$ c #007A72",
"T$ c #C3C2C2",
"U$ c #BFBFC0",
"V$ c #BEBDBE",
"W$ c #BCBBBB",
"X$ c #00857C",
"Y$ c #007D77",
"Z$ c #007C76",
"`$ c #007B74",
" % c #007A73",
".% c #007972",
"+% c #C3C4C3",
"@% c #C5C5C6",
"#% c #BEBFBF",
"$% c #007871",
"%% c #BCBDBC",
"&% c #C4C5C4",
"*% c #C6C6C5",
"=% c #007770",
"-% c #00766F",
";% c #C3C2C3",
">% c #008C85",
",% c #007F77",
"'% c #007872",
")% c #00766E",
"!% c #C8C7C7",
"~% c #C7C6C6",
"{% c #C5C5C4",
"]% c #C2C0C1",
"^% c #B3B3B4",
"/% c #007E76",
"(% c #007870",
"_% c #00756F",
":% c #00756D",
"<% c #C9C8C8",
"[% c #C5C4C4",
"}% c #007A74",
"|% c #007971",
"1% c #00746E",
"2% c #00746D",
"3% c #C7C7C7",
"4% c #008881",
"5% c #00756E",
"6% c #00746C",
"7% c #00736C",
"8% c #00716A",
"9% c #C8C9C8",
"0% c #00716B",
"a% c #C6C7C7",
"b% c #CACBCA",
"c% c #C9C8CA",
"d% c #007771",
"e% c #00726B",
"f% c #006F69",
"g% c #007670",
"h% c #007069",
"i% c #006E68",
"j% c #000303",
"k% c #007169",
"l% c #007068",
"m% c #006D67",
"n% c #AEAFAE",
"o% c #00736B",
"p% c #00726A",
"q% c #A9A9A8",
"r% c #CFCFCF",
"s% c #C5C4C5",
"t% c #007973",
"u% c #00736D",
"v% c #006F68",
"w% c #B0AEB0",
"x% c #00726C",
"y% c #006D68",
"z% c #007C74",
"A% c #00706A",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . + @ # ",
" $ $ $ $ $ $ $ $ $ $ $ % & * * = - ; > , ' ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) ! ~ { { ~ ] ^ / ( _ : ~ < ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ [ } | 1 2 3 4 5 6 7 $ $ $ $ $ $ 8 9 0 a b c d e ",
" $ $ $ $ $ $ $ $ $ $ f f g h i j k l m | | n 2 o p 5 6 q r s t $ $ $ $ u v w x ( ^ 8 ",
" $ $ $ $ $ $ $ $ y z z A A B C D E F G H I l J | n n 3 K 5 6 q q L M N $ $ $ $ O ( b P Q R * ",
" $ $ $ $ $ $ S S S T S U V V z W X C g E Y G H Z [ J | n ` .p ..7 +.@.#.$.%.&.$ $ $ *.=.-.;.>.,.'. ",
" $ $ $ $ $ U T T T ).).).T T S U V z B !.!.g F Y H I l ~.| {.].3 p 5 6 q @.s t %.&.^.$ $ $ /.(._.:.<.[.}. ",
" $ $ $ $ y |.T ).).1.1.1.1.2.3.4.T y y A B !.5.6.F j 7.Z [ 8.1 2 3 4 9.6 7 +.s t N 0.a.b.$ $ $ * c.d.e.f.g.'. ",
" $ $ $ $ A h.|.S 4.2.1.i.i.j.i.i.k.2.l.T y z A m.f g E i n.Z [ } | n 2 4 p o.7 +.L p.q.0.&.b.r.$ $ s.t.u.v.w.x.y. ",
" $ $ $ !.B z.y S T 1.i.j.A.B.B.C.B.D.k.3.4.S y z W !.f E Y G k [ J | E.F.o p o.7 q L M q.%.&.G.H.$ $ $ I.J.u.K.L.M.N. ",
" $ $ $ $ m.A h.S T 2.O.D.B.P.Q.Q.R.S.B.T.O.).T U V A !.f U.V.j n.l m | {.2 o 4 5 W.q X.#.t %.a.Y.Z.`.$ $ $ 9 0 +.+++e.@+u ",
" $ $ $ $ #+h.S 4.1.T.C.P.Q.$+$+$+Q.%+D.i.1.T |.h.A !.f g h G H l ~.} E.2 3 p 5 7 q r #.N %.&.&+*+=+`.$ $ - -+;+>+Q ,+'+ ",
" $ $ $ y T ).1.D.B.)+$+!+~+{+]+P.B.j.1.T S y A B !.g h G H l J | E.n 3 p p ^+/+@.#.t %.&.(+_+:+<+[+$ $ 9 }+|+1+2+3+4+5+ ",
" $ $ y T ).O.D.%+)+$+~+6+{+$+P.B.T.1.).S y A B f g F G H I [ 8.{.n .4 5 6 /+X.7+t %.&.8+9+0+<+[+$ $ $ - a+b+c+d+e+-+f+ ",
" $ $ $ T ).1.D.S.Q.$+{+g+{+$+R.A.D.1.).S z z.B h+6.F G 7.Z ~.8.E.].3 i+5 7 q @.#.t j+&.k+l+m+n+o+p+$ $ f+q+r+s+t+b+u+v+f+ ",
" $ $ $ l.2.D.C.%+Q.$+$+w+Q.P.D.i.1.l.S y A X f U.F G H l J } E.2 3 p o.6 q r #.$.%.&.G.x+y+z+A+p+B+$ $ C+q+D+E+F+x.G+H+|+I+O ",
" $ $ $ 3.i.D.B.P.P.Q.)+P.B.D.O.).T S z A m.f E F G 7.l J | {.2 .p ..6 q L #.q.%.&.G.J+K+L+M+N+O+P+Q+R+ S+T+U+V+W+V+X+Y+Z+`+ @-+.@L+ ",
" $ $ 4.1.k.j.A.B.B.B.C.j.i.).T S y A B !.f U.F +@k @@J | n 2 o p ..W.q @.t N %.a.b.#@$@%@&@*@=@-@;@}+>@,@'@)@/ !@~@D+V+X+{@]@^@/@(@_@ ",
" $ $ $ ).1.O.D.D.i.D.j.1.2.l.S |.z A m.C g E Y H k [ 8.| n ` 4 9.o.7 q L t q.%.a.b.:@<@[@}@|@1@;@2@3@g.4@5@6@7@8@9@)@0@a@b@E+c@H+d@e@ ",
" $ $ T ).).3.1.k.O.1.).4.T |.z A W !.f U.F +@7.l [ | E.f@` 4 5 W./+g@L p.N %.a.H.:+`.h@i@j@k@l@m@n@o@_ _ p@5@q@r@9@s@t@-+V+E+u@b+;@v@ ",
" $ $ $ S T T ).).T l.T S |.y #+W X f g h G H Z @@J | 1 2 3 i+5 7 q X.s t N &.^.w@:+<+o+x@y@z@A@B@C@D@a+m@E@4@/@5@7@F@s@t@0@G@H@{@(.=.A@ ",
" $ $ y U S S S S S U y z A A m.C g E F G n.Z [ 8.| n 2 4 I@5 W.q r #.q.%.&.a.H.`.J@K@p+B+L@M@N@O@P@Q@e@v@R@S@/@5@7@8@9@~@t@G@T@x.T@U@e@ ",
" V@$ $ z y V y y h.V z.A B m.!.D 6.F G H Z W@J | E.2 3 4 I@6 7 @.s M $.X@&.^.:@=+<+Y@p+Z@L@`@ #.#+#@### $#%#4@0 /@5@7@9@s@t@-+a@x.&#*#.@ ",
" $ $ A A z.A z #+=#A m.!.!.D 6.F G j k l m | | n 2 4 p 5 7 q r L t N &.a.b.:+-#;#Y@p+Z@>#,#'#)#!#$ $ ~#3@4@_ /@5@r@{#9@s@W+]#x.0 ^#$# ",
" $ $ $ B B B B B X !.f f g E V.F j k l [ J | 1 ].3 4 5 6 7 @.L #.q.%.&.^.H.:+J@o+Y@/#Z@(#_#:#<#!#$ $ $ q+[#4@_ 0 /@q@8@&#s@t@-+c@m@}#|# ",
" $ $ !.!.!.!.h+f D g 6.E F G H H l [ ~.| E.].F. .p 5 7 q @.s M N X@a.b.:@`.<+Y@p+B+>#`@1#:#<#2#3#$ $ 4#U@5#4@6#7#c.5@8#9@9#0#-+]@5#q+ ",
" $ $ $ g g g g 6.E h F G j H k Z @@J | | n 2 o p 5 6 7 @.X.#.t %.X@a.H.:+`.;#Y@a#b#>#c#'#:#!#d#3#$ $ ~#R@c e#4@f#0 5@g#8@h#s@i#j#k#k@ ",
" $ $ E F E V.h Y Y G H k k l [ J | E.n 2 3 4 9.6 W.q @.L t N %.&.b.:@=+J@o+p+B+Z@(#_#'#<#!#3#l#m#$ $ q+n#c o#n@_ 0 /@7@8#9@p#W+s@1@q# ",
" $ $ G i G G +@+@H k k I @@J J | E.{.2 3 4 p 5 6 r#@.L M $.%.X@a.b.:+J@<+o+p+b#>#`@1#s#<#!#3#t#u#$ $ U@2@d@a+4@v#w#0 q@r@9@x#-+7@y#*# ",
" $ $ H 7.7.H k k l [ [ ~.} E.E.n 2 3 4 p 5 6 /++.L L t %.&.&.b.H.:+J@o+Y@a#Z@z#_#'#<#<#d#3#t#u#$ $ $ A#B#d@C#D#E#F#,.G#7@H#I#J#F#y#U@ ",
" $ $ Z l l l l W@[ J } | E.{.].F.3 4 p I@^+7 +.X.#.M $.%.&.a.K#:@`.;#[+L#B+>#`@_#M#<#!#N#O#P#u#Q#$ $ y#;@R#m@S#T#_ 0 /@5@r@/ -+S#=. ",
" $ $ $ [ [ J J J 8.| E.{.n ].2 3 4 p 5 6 7 q @.L #.q.%.&.a.w@r.`.J@o+p+p+Z@>#_#U#:#!#d#3#V#W#X#Y#$ $ Z#[#c m@S#T#`#f#,.p@7@h# $m@y# ",
" $ $ } | 8.E.| E.1 n n 2 3 4 K I@5 6 /+q r L #.$..$X@a.b.H.:+-#o+Y@a#Z@>#`@'#'#<#!#3#l#m#+$Q#Y#@$$ $ C@#$5#g.c a+S@$$_ v+%$&$*$9@g.%# ",
" $ $ E.E.E.n n ].].F.3 4 K p 5 ..6 7 +.@.L #.t N %.&.b.H.:+`.<+o+L#B+Z@>#_#U#:#!#=$3#m#u#X#Q#-$;$$ $ >$3@[#g.c a+,$n@_ ,./@5@'$g#;@C@ ",
" $ $ $ f@2 2 2 ` 3 4 K p p 5 6 ^+/+g@@.L #.t N %.&.a.b.:@:+`.o+L#B+b#L@c#U#:#)#2#N#3#m#X#)$Y#@$!$$ $ $ 3@~${$]$^$m@a+S#4@f#,.5@8@/@/$($ ",
" $ $ 3 3 4 4 4 K p I@5 5 6 q q @.r #.M t N %.&.G.K#r.=+<+_$K@p+B+L@(#,#'#:$<#d#l#V#W#X#Q#@$;$<$[$$ $ ;@3@[#5#g.}$C#|$4@_ 1$/@2$7#3$3@ ",
" $ $ p i+K p 9.5 o.6 W.7 r#+.r L #.t q.N 0.a.G.b.:+=+J@;#Y@p+B+Z@z#`@1#:#<#=$3#t#m#u#4$Y#@$5$6$7$$ $ [#P@;@8$g.9$0$|$S#_ 0 /@a$E#;@ ",
" $ $ 5 5 ....o.6 6 /+q q @.L #.#.p.N %.0.&.G.K#r.=+-#<+Y@L#B+Z@>#`@_#'#:#!#d#3#t#u#X#Q#-$b$c$d$e$$ $ $ [#;@;@[#]$c R#a+,$n@f$0 a$S#{$ ",
" $ $ 6 W.7 r#q q +.@.L L #.#.q.j+%.0.a.G.w@:@:+`.;#o+L#B+B+g$(#_#'#)#<#d#3#t#P#X#Q#Y#@$!$6$h$e$i$$ $ g.{$B#k#D@j$k$0$a+S@n@_ 0 /@m@]$ ",
" $ $ q q q g@@.r L L #.M t N .$0.&.a.b.H.:@`.<+;#[+Y@B+l$g$`@_#'#:#<#!#d#l#m#u#X#m$-$;$c$7$e$n$o$$ $ c '@3@p$;@5#g.c m@a+S#`#0 1$C#c ",
" $ $ L r L #.s s M p.$.N %.%.0.a.a.b.H.:+`.`._$Y@p+a#b#g$(#_#'#'#)#!#q$3#V#u#X#Q#-$b$c$6$7$r$i$o$$ $ $ C#8$#$s$;@t$u$g.m@v$w$4@_ 1$v$0$ ",
" $ $ $ #.#.#.t t q.N %.%.&.&.a.b.w@r.:+x$<+o+K@p+p+Z@>#z#c#'#s#:$<#d#3#t#P#X#)$Y#y$;$<$d$e$i$z$A$B$$ $ a+3$C$l@k#[#'@^$c m@S#e#_ F#a+D$ ",
" $ $ N N N .$j+%.%.&.&.a.b.K#H.H.`.-#<+o+Y@E$a#Z@L@(#,#'#M#<#!#d#3#t#u#X#Q#Y#@$;$c$6$h$F$z$o$G$H$$ $ a+I$Q@1@;@;@J$g.c m@K$4@_ 4@S# ",
" $ $ j+X@&.X@&.&.a.^.G.K#H.:@:+J@J@o+[+Y@p+B+Z@>#z#,#U#:#<#<#!#N#t#m#u#X#Q#L$;$c$6$M$e$N$o$G$B$O$$ $ $ a+k#C@C$l@;@/$5#g.c P$S@4@4@4@ ",
" $ $ a.a.a.^.a.b.b.H.H.:+`.`.<+o+o+K@L#p+B+Z@>#`@_#'#:#)#<#2#3#t#m#u#X#Q#-$@$5$6$[$e$i$o$G$B$Q$R$S$$ $ v+,$T$y#C$1@3@U$J$V$c W$|$S#_ 4@ ",
" $ $ $ b.b.K#w@:@:+:+`.-#`._$o+K@Y@p+B+Z@L@z#`@_#'#M#<#<#=$q$t#m#u#X#Q#Y#@$5$X$d$e$F$z$A$Y$Z$`$ %.%$ $ 5@C#+%@%C$>$3@;@#%5#g.E@t.S#_ v+ ",
" $ $ :@H.:+=+:+`.-#<+_$o+[+E$p+B+B+L@>#(#`@U#'#:$<#!#d#3#O#V#u#X#)$Y#@$;$c$6$7$F$z$o$G$H$Q$R$.%$%$ $ q@%%&%*%n#C$1@3@[#]$g.d@K$,$0 5@ ",
" $ $ `.`.`.<+_$;#o+K@K@E$p+a#l$B+>#>#c#,#1#:#:#<#2#d#3#t#m#u#+$Q#Y#@$;$c$6$7$r$N$z$A$B$Q$`$.%.%=%-%$ $ 5@]$R@R@C@Q@;%k#D@#%5#^$c S#/@5@ ",
" $ $ <+_$_$o+[+[+Y@p+a#a#l$Z@L@>#(#_#1#'#'#:$!#=$N#3#t#>%u#X#Q#m$@$;$c$6$7$r$n$o$,%Y$Q$`$ %'%$%-%)%$ $ 5@[#!%~%{%C@>$]%p$;@t$5#g.4@^%5@ ",
" $ $ Y@Y@Y@Y@p+a#B+B+l$Z@Z@z#`@,#1#1#M#)#<#!#=$N#l#t#m#u#X#4$Y#@$;$c$6$7$e$n$z$G$/%Q$`$R$.%(%=%_%:%$ $ /@3@<%R@=.C@[%C$ /@5@ ",
" $ $ $ p+B+B+b#l$Z@Z@>#(#`@`@_#'#'#:#<#<#!#d#3#t#>%m#u#X#m$Y#@$;$c$6$7$e$n$z$o$G$H$Q$}%.%|%=%_%1%2%$ $ $ ]#,.C$|@3%y#C@ r@o# ",
" $ $ Z@Z@g$Z@>#>#`@c#_#_#'#:#:#:$!#!#d#d#t#t#V#u#u#X#4%Y#@$;$c$6$7$e$N$z$o$G$H$O$ %.%'%=%-%5%6%7%8%$ $ V+_ R@9%U@3% 4@9@ ",
" $ $ >#(#z#`@,#_#1#'#'#s#:#<#!#!#2#N#3#t#>%P#u#X#Q#Y#-$@$;$c$6$7$r$n$z$o$G$Z$`$`$ %.%=%-%_%2%7%0%8%$ $ -+|$a%b%c% c I# ",
" $ $ _#_#1#1#'#'#s#:#<#<#!#!#=$d#3#t#t#m#u#X#X#Q#Y#L$;$;$6$[$M$e$n$z$o$G$B$Q$`$ %.%d%=%5%2%7%e%8%f%$ $ r+%%q+B@ m@s@ ",
" $ $ M#M#s#:#:#:$<#!#<#!#d#q$3#t#t#m#m#u#X#Q#4%Y#@$;$5$<$6$e$e$i$z$A$Y$H$Q$`$S$.%(%g%5%1%6%e%8%h%i%$ $ j% -+[#,@ R@F@s@ ",
" $ $ )#<#<#<#!#!#!#d#N#q$l#l#V#m#W#u#X#Q#4%Y#-$;$;$c$6$7$M$r$z$z$o$G$H$Q$`$ %|%d%=%_%1%6%e%8%k%l%i%m%$ $ ~@3@~# *#%%n% ",
" $ $ $ !#2#d#q$d#3#3#t#t#m#P#u#u#X#)$4%Y#Y#@$;$!$X$[$7$M$F$i$z$,%Y$B$Q$`$S$.%$%g%-%5%2%o%p%h%h%i%m%m%$ $ q%9@m@3%r%}#s%c V+n% ",
" $ $ d#3#3#3#O#t#V#m#u#u#+$X#)$Q#Y#-$@$b$5$c$6$7$M$e$n$z$o$G$Y$Q$Q$R$t%'%$%=%_%2%u%7%p%8%f%v%m%m%m%$ $ 7@-+V+v s@X+X+ ",
" $ $ t#t#>%m#P#u#u#+$X#)$Q#Y#Y#-$b$b$;$c$6$7$h$e$F$z$o$o$G$B$Z$O$ % %.%d%-%-%1%6%7%0%k%f%v%m%m%m%m%$ $ 7@w%F@ ",
" $ $ u#u#u#u#u#X#Q#)$m$4%Y#@$@$b$!$c$6$6$h$M$e$n$z$z$A$G$B$Q$`$ %.%.%=%=%5%:%u%x%p%8%l%i%y%m%m%m%m%$ $ ",
" $ $ X#X#4$Q#Q#Q#m$Y#@$y$;$;$!$c$6$d$7$7$e$n$N$z$o$G$B$H$z%`$t%.%$%$%g%_%2%6%7%p%k%h%i%i%m%m%m%m%m%m%$ $ ",
" $ $ Y#Y#4%Y#Y#-$y$@$;$5$c$X$6$6$7$h$e$n$n$o$o$,%Y$Z$Q$`$`$ %.%(%=%-%)%2%7%x%0%h%h%i%m%m%m%m%m%m%m%m%$ $ ",
" $ $ @$b$;$@$;$;$!$c$c$6$6$7$7$e$r$n$N$z$o$,%G$B$B$Q$`$ %t%$%$%g%-%5%2%7%e%8%A%h%v%m%m%m%m%m%m%m%m%m%$ $ ",
" $ $ ;$5$!$c$X$c$6$6$7$7$h$e$n$n$z$z$o$,%G$Y$B$Q$z% % %.%$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ m%$ $ ",
" $ $ X$6$6$6$[$7$7$h$F$F$n$N$z$o$o$,%B$B$B$Q$`$R$$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ 7$7$h$e$e$n$n$i$i$z$z$o$,%G$/%B$Q$Q$`$$ $ $ $ $ $ $ $ $ $ $ ",
" $ $ n$n$n$n$z$z$z$o$o$,%,%G$B$B$Q$Q$$ $ $ $ $ $ $ ",
" $ $ z$z$o$z$o$o$G$G$/%/%B$Z$Q$$ $ $ $ $ $ $ ",
" $ $ A$A$G$G$G$/%B$Q$H$O$z%$ $ $ $ $ $ ",
" $ $ B$B$B$Z$Q$Q$`$`$$ $ $ $ $ $ ",
" $ $ O$`$`$`$`$R$$ $ $ $ $ $ ",
" $ $ }% % % %$ $ $ $ $ $ $ ",
" $ $ |%$%$ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ ",
" j%$ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ $ $ $ $ $ $ $ $ $ $ $ ",
" $ $ $ ",
" $ $ $ ",
" ",
" ",
" "};

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

View File

@@ -0,0 +1,865 @@
/* XPM */
static char * SliceIco_xpm[] = {
"128 128 734 2",
" c None",
". c #008F00",
"+ c #009100",
"@ c #008700",
"# c #007800",
"$ c #007700",
"% c #009900",
"& c #007B00",
"* c #007500",
"= c #007400",
"- c #007F00",
"; c #008D00",
"> c #008000",
", c #007900",
"' c #009F00",
") c #009000",
"! c #007D00",
"~ c #007600",
"{ c #008100",
"] c #008A00",
"^ c #008E00",
"/ c #009300",
"( c #009E00",
"_ c #00B200",
": c #00D600",
"< c #009400",
"[ c #00A100",
"} c #008800",
"| c #007A00",
"1 c #008300",
"2 c #00A500",
"3 c #00C000",
"4 c #00EA00",
"5 c #00FF00",
"6 c #009D00",
"7 c #007C00",
"8 c #008900",
"9 c #00E700",
"0 c #00FD00",
"a c #00FE00",
"b c #009C00",
"c c #00A700",
"d c #007300",
"e c #00A000",
"f c #00C200",
"g c #00F400",
"h c #00F700",
"i c #00FA00",
"j c #00A300",
"k c #007000",
"l c #00C100",
"m c #00DF00",
"n c #00E900",
"o c #00EF00",
"p c #008200",
"q c #008500",
"r c #007100",
"s c #007E00",
"t c #00AE00",
"u c #00CA00",
"v c #00D400",
"w c #00D700",
"x c #00DE00",
"y c #00E800",
"z c #00F600",
"A c #008C00",
"B c #008600",
"C c #007200",
"D c #008400",
"E c #00A900",
"F c #00BE00",
"G c #00C500",
"H c #00CC00",
"I c #00DA00",
"J c #00ED00",
"K c #009200",
"L c #00AD00",
"M c #00B700",
"N c #00C600",
"O c #00D800",
"P c #009800",
"Q c #00A800",
"R c #00BA00",
"S c #00D100",
"T c #00F200",
"U c #00B500",
"V c #00D500",
"W c #00FC00",
"X c #00EE00",
"Y c #00A200",
"Z c #00C900",
"` c #00EB00",
" . c #00F300",
".. c #00FB00",
"+. c #008B00",
"@. c #00E300",
"#. c #00F100",
"$. c #02FF02",
"%. c #03FF03",
"&. c #05F805",
"*. c #00BF00",
"=. c #05FF05",
"-. c #01FF01",
";. c #000000",
">. c #2DEC2D",
",. c #2DEC2C",
"'. c #2CEB2C",
"). c #2BEA2B",
"!. c #2AE92A",
"~. c #BDBDBD",
"{. c #BCBDBD",
"]. c #BCBCBC",
"^. c #BABBBA",
"/. c #FF0000",
"(. c #2AE82A",
"_. c #29E829",
":. c #C1C2C2",
"<. c #C1C1C1",
"[. c #C0C1C1",
"}. c #C0C0C0",
"|. c #BFC0C0",
"1. c #BFBFBF",
"2. c #BEBDBE",
"3. c #BCBDBC",
"4. c #BBBBBB",
"5. c #BABABA",
"6. c #2CEA2B",
"7. c #C3C3C3",
"8. c #C4C3C3",
"9. c #C3C3C4",
"0. c #C3C4C3",
"a. c #C3C2C3",
"b. c #C2C1C2",
"c. c #C1C1C2",
"d. c #BFC0BF",
"e. c #BEBEBF",
"f. c #BDBDBE",
"g. c #BDBCBC",
"h. c #BCBBBB",
"i. c #BABAB9",
"j. c #B9B9B9",
"k. c #2BEB2B",
"l. c #2BE92B",
"m. c #28E728",
"n. c #C2C2C3",
"o. c #C4C4C4",
"p. c #C5C5C5",
"q. c #C4C5C5",
"r. c #C5C4C4",
"s. c #BEBEBE",
"t. c #BDBEBE",
"u. c #BBBABA",
"v. c #B8B8B8",
"w. c #29E728",
"x. c #C2C2C2",
"y. c #C3C3C2",
"z. c #C5C6C6",
"A. c #C6C6C6",
"B. c #C7C6C6",
"C. c #C6C6C5",
"D. c #C6C5C6",
"E. c #C4C5C4",
"F. c #C3C4C4",
"G. c #C3C2C2",
"H. c #C1C0C0",
"I. c #C0BFBF",
"J. c #BDBCBD",
"K. c #BBBCBB",
"L. c #B8B8B9",
"M. c #B8B8B7",
"N. c #28E829",
"O. c #27E728",
"P. c #C2C2C1",
"Q. c #C2C3C2",
"R. c #C5C5C4",
"S. c #C7C7C7",
"T. c #C8C8C7",
"U. c #C6C6C7",
"V. c #C5C4C5",
"W. c #BFBFBE",
"X. c #BABBBB",
"Y. c #BAB9BA",
"Z. c #B8B7B8",
"`. c #B7B7B6",
" + c #2BEB2C",
".+ c #2AEA2A",
"++ c #27E627",
"@+ c #C1C1C0",
"#+ c #C9C8C9",
"$+ c #C9C9C9",
"%+ c #C9C9C8",
"&+ c #C8C9C9",
"*+ c #C8C8C8",
"=+ c #C7C6C7",
"-+ c #B7B7B7",
";+ c #B6B5B5",
">+ c #2CEA2C",
",+ c #C7C7C6",
"'+ c #C9CACA",
")+ c #CACBCB",
"!+ c #CACBCA",
"~+ c #CAC9CA",
"{+ c #C7C7C8",
"]+ c #BCBBBC",
"^+ c #BABABB",
"/+ c #B9B8B9",
"(+ c #B6B6B6",
"_+ c #B5B4B5",
":+ c #2AE929",
"<+ c #C0C0C1",
"[+ c #C8C9C8",
"}+ c #CACACA",
"|+ c #CBCBCB",
"1+ c #CCCCCC",
"2+ c #C9CAC9",
"3+ c #C9C8C8",
"4+ c #BFBEBE",
"5+ c #B5B5B4",
"6+ c #B4B4B3",
"7+ c #04F204",
"8+ c #CBCACB",
"9+ c #CDCECD",
"0+ c #CECDCE",
"a+ c #CDCDCD",
"b+ c #CBCBCC",
"c+ c #BBBBBA",
"d+ c #B7B6B6",
"e+ c #B5B4B4",
"f+ c #B3B3B3",
"g+ c #B2B2B2",
"h+ c #26E526",
"i+ c #C6C7C6",
"j+ c #CACACB",
"k+ c #CFCFCE",
"l+ c #C8C7C8",
"m+ c #BAB9B9",
"n+ c #B7B8B8",
"o+ c #B6B6B7",
"p+ c #B5B5B5",
"q+ c #B3B3B4",
"r+ c #B2B2B1",
"s+ c #29E929",
"t+ c #C4C4C3",
"u+ c #C9C9CA",
"v+ c #CECECE",
"w+ c #CBCCCC",
"x+ c #C2C1C1",
"y+ c #C0C1C0",
"z+ c #BEBEBD",
"A+ c #BCBCBB",
"B+ c #B7B8B7",
"C+ c #B6B7B6",
"D+ c #B4B5B4",
"E+ c #B0B1B0",
"F+ c #28E729",
"G+ c #C7C8C8",
"H+ c #CACAC9",
"I+ c #CBCCCB",
"J+ c #BFBEBF",
"K+ c #B4B4B4",
"L+ c #B3B4B3",
"M+ c #B0B0B0",
"N+ c #AEAFAF",
"O+ c #C5C5C6",
"P+ c #CBCACA",
"Q+ c #C6C5C5",
"R+ c #C2C3C3",
"S+ c #BEBFBE",
"T+ c #B1B2B1",
"U+ c #AFAEAF",
"V+ c #ADADAD",
"W+ c #2AE829",
"X+ c #25E425",
"Y+ c #B8B9B8",
"Z+ c #B5B6B5",
"`+ c #B1B1B1",
" @ c #AEAFAE",
".@ c #27E526",
"+@ c #26E525",
"@@ c #C8C7C7",
"#@ c #C7C8C7",
"$@ c #C5C6C5",
"%@ c #C4C4C5",
"&@ c #B9BAB9",
"*@ c #B6B7B7",
"=@ c #B0B0AF",
"-@ c #AEAEAE",
";@ c #ADADAC",
">@ c #ABACAB",
",@ c #27E527",
"'@ c #26E425",
")@ c #B9B9B8",
"!@ c #B1B0B1",
"~@ c #AFB0AF",
"{@ c #ADACAC",
"]@ c #ABAAAB",
"^@ c #28E627",
"/@ c #26E527",
"(@ c #C1C0C1",
"_@ c #B2B1B2",
":@ c #AFAFAF",
"<@ c #AEADAE",
"[@ c #ACACAC",
"}@ c #ABAAAA",
"|@ c #AAA9A9",
"1@ c #27E727",
"2@ c #25E325",
"3@ c #B8B9B9",
"4@ c #B7B7B8",
"5@ c #B3B3B2",
"6@ c #ADACAD",
"7@ c #AAAAAB",
"8@ c #A9A9A9",
"9@ c #A7A7A8",
"0@ c #24E324",
"a@ c #084808",
"b@ c #BDBDBC",
"c@ c #B5B5B6",
"d@ c #ACACAD",
"e@ c #ABABAB",
"f@ c #A9AAAA",
"g@ c #A8A8A8",
"h@ c #A7A7A6",
"i@ c #C0BFC0",
"j@ c #AFB0B0",
"k@ c #ABACAC",
"l@ c #AAAAAA",
"m@ c #A8A7A8",
"n@ c #A7A7A7",
"o@ c #A5A5A5",
"p@ c #BBBABB",
"q@ c #B9BABA",
"r@ c #ADAEAE",
"s@ c #A6A6A6",
"t@ c #A4A4A5",
"u@ c #BDBEBD",
"v@ c #B1B2B2",
"w@ c #B0AFB0",
"x@ c #AEAEAF",
"y@ c #A6A7A6",
"z@ c #A5A6A5",
"A@ c #A4A4A4",
"B@ c #25E526",
"C@ c #25E424",
"D@ c #23E224",
"E@ c #23E223",
"F@ c #B4B3B3",
"G@ c #AFAFAE",
"H@ c #AEADAD",
"I@ c #A9A8A8",
"J@ c #A7A8A7",
"K@ c #A4A5A5",
"L@ c #A3A3A3",
"M@ c #A2A2A3",
"N@ c #25E324",
"O@ c #04E804",
"P@ c #B9B8B8",
"Q@ c #B2B1B1",
"R@ c #ACABAB",
"S@ c #A5A4A4",
"T@ c #A2A3A3",
"U@ c #A2A2A1",
"V@ c #B9B9BA",
"W@ c #B1B0B0",
"X@ c #AAAAA9",
"Y@ c #A6A6A5",
"Z@ c #A5A5A4",
"`@ c #A1A1A1",
" # c #9FA0A0",
".# c #25E525",
"+# c #24E424",
"@# c #23E324",
"## c #23E122",
"$# c #B3B2B3",
"%# c #A9A9AA",
"&# c #A9A9A8",
"*# c #A8A7A7",
"=# c #A6A7A7",
"-# c #A2A2A2",
";# c #A1A0A0",
"># c #9F9F9F",
",# c #22E122",
"'# c #B1B1B0",
")# c #AFAFB0",
"!# c #ABABAA",
"~# c #A8A8A7",
"{# c #A7A6A6",
"]# c #A4A5A4",
"^# c #9F9FA0",
"/# c #9E9F9E",
"(# c #9D9D9D",
"_# c #23E123",
":# c #B2B2B3",
"<# c #A5A6A6",
"[# c #A5A4A5",
"}# c #A0A09F",
"|# c #9F9E9F",
"1# c #9C9D9C",
"2# c #24E325",
"3# c #24E223",
"4# c #23E222",
"5# c #B2B3B3",
"6# c #B1B1B2",
"7# c #AEAEAD",
"8# c #AAA9AA",
"9# c #A8A9A9",
"0# c #A4A4A3",
"a# c #A3A2A3",
"b# c #9D9E9E",
"c# c #9C9C9D",
"d# c #9C9B9B",
"e# c #21E021",
"f# c #AFAEAE",
"g# c #ABABAC",
"h# c #A3A4A4",
"i# c #A09F9F",
"j# c #9E9E9E",
"k# c #9C9C9C",
"l# c #9A9B9B",
"m# c #99999A",
"n# c #23E323",
"o# c #21E022",
"p# c #ADAEAD",
"q# c #ACADAD",
"r# c #AAABAA",
"s# c #A9A8A9",
"t# c #A7A8A8",
"u# c #9C9D9D",
"v# c #9B9B9B",
"w# c #9A999A",
"x# c #999898",
"y# c #24E224",
"z# c #AAABAB",
"A# c #A1A2A2",
"B# c #A0A1A0",
"C# c #9E9E9F",
"D# c #9D9E9D",
"E# c #9B9C9B",
"F# c #9A9B9A",
"G# c #999999",
"H# c #989898",
"I# c #22E222",
"J# c #22E021",
"K# c #20E020",
"L# c #ADADAE",
"M# c #ACADAC",
"N# c #A8A9A8",
"O# c #A2A3A2",
"P# c #A2A1A2",
"Q# c #A1A1A0",
"R# c #A0A0A0",
"S# c #9F9E9E",
"T# c #9E9E9D",
"U# c #9B9B9C",
"V# c #9A9A9A",
"W# c #979797",
"X# c #24E323",
"Y# c #20DF20",
"Z# c #ACABAC",
"`# c #A5A5A6",
" $ c #A09FA0",
".$ c #9D9C9D",
"+$ c #969696",
"@$ c #959595",
"#$ c #21DF21",
"$$ c #A4A3A4",
"%$ c #9FA09F",
"&$ c #9F9F9E",
"*$ c #9C9B9C",
"=$ c #969796",
"-$ c #959596",
";$ c #949494",
">$ c #A8A8A9",
",$ c #A3A3A2",
"'$ c #9E9D9D",
")$ c #9B9A9B",
"!$ c #999A9A",
"~$ c #979798",
"{$ c #939393",
"]$ c #1FDE1F",
"^$ c #A4A3A3",
"/$ c #A1A1A2",
"($ c #A0A1A1",
"_$ c #999998",
":$ c #989897",
"<$ c #929393",
"[$ c #22E022",
"}$ c #A6A5A5",
"|$ c #A1A2A1",
"1$ c #9D9D9E",
"2$ c #989797",
"3$ c #969695",
"4$ c #959495",
"5$ c #929293",
"6$ c #919291",
"7$ c #909190",
"8$ c #20DF21",
"9$ c #1FDF20",
"0$ c #A3A3A4",
"a$ c #9E9F9F",
"b$ c #999A99",
"c$ c #989998",
"d$ c #969697",
"e$ c #969596",
"f$ c #949594",
"g$ c #949393",
"h$ c #929392",
"i$ c #919191",
"j$ c #909090",
"k$ c #8F8F8F",
"l$ c #20E021",
"m$ c #A0A0A1",
"n$ c #9D9D9C",
"o$ c #959594",
"p$ c #949394",
"q$ c #939292",
"r$ c #8F9090",
"s$ c #8E8F8E",
"t$ c #21E121",
"u$ c #1FDD1F",
"v$ c #969595",
"w$ c #959494",
"x$ c #929292",
"y$ c #929192",
"z$ c #909191",
"A$ c #8F8F90",
"B$ c #8E8E8E",
"C$ c #8D8D8D",
"D$ c #20DE1F",
"E$ c #1EDD1E",
"F$ c #9C9C9B",
"G$ c #9B9B9A",
"H$ c #929191",
"I$ c #8F908F",
"J$ c #8E8E8F",
"K$ c #8C8C8C",
"L$ c #9A9A9B",
"M$ c #9A9A99",
"N$ c #979898",
"O$ c #979697",
"P$ c #949595",
"Q$ c #929291",
"R$ c #908F8F",
"S$ c #8E8E8D",
"T$ c #8C8D8C",
"U$ c #8B8B8B",
"V$ c #8A8A8A",
"W$ c #1EDE1F",
"X$ c #059A05",
"Y$ c #9D9C9C",
"Z$ c #989798",
"`$ c #959696",
" % c #939493",
".% c #919292",
"+% c #8A8B8A",
"@% c #898989",
"#% c #1FDF1F",
"$% c #1DDC1D",
"%% c #9B9C9C",
"&% c #949493",
"*% c #919090",
"=% c #8F8F8E",
"-% c #8C8C8D",
";% c #898988",
">% c #1FDE20",
",% c #1DDD1E",
"'% c #969797",
")% c #90908F",
"!% c #8D8D8E",
"~% c #89898A",
"{% c #888888",
"]% c #878787",
"^% c #1FDD1E",
"/% c #1EDD1D",
"(% c #017501",
"_% c #939494",
":% c #8E8D8D",
"<% c #8D8C8D",
"[% c #868686",
"}% c #1CDC1D",
"|% c #004C00",
"1% c #979796",
"2% c #8E8F8F",
"3% c #898A8A",
"4% c #898889",
"5% c #858585",
"6% c #1DDC1C",
"7% c #1CDB1C",
"8% c #959695",
"9% c #939293",
"0% c #919091",
"a% c #8C8B8C",
"b% c #8A8989",
"c% c #878788",
"d% c #848585",
"e% c #848484",
"f% c #838383",
"g% c #1EDC1D",
"h% c #8C8B8B",
"i% c #898888",
"j% c #878887",
"k% c #878686",
"l% c #858686",
"m% c #858484",
"n% c #848483",
"o% c #828283",
"p% c #828282",
"q% c #1EDC1E",
"r% c #1CDA1C",
"s% c #888889",
"t% c #868586",
"u% c #848485",
"v% c #838282",
"w% c #808180",
"x% c #1CDC1C",
"y% c #1BDA1B",
"z% c #020A02",
"A% c #8E8D8E",
"B% c #8D8D8C",
"C% c #8C8C8B",
"D% c #888788",
"E% c #818182",
"F% c #818080",
"G% c #808080",
"H% c #1BDB1B",
"I% c #1B901B",
"J% c #000600",
"K% c #898A89",
"L% c #858685",
"M% c #858584",
"N% c #828383",
"O% c #818281",
"P% c #7F807F",
"Q% c #7F7F7E",
"R% c #1BDB1C",
"S% c #8D8E8D",
"T% c #8B8B8A",
"U% c #868786",
"V% c #858586",
"W% c #818282",
"X% c #818181",
"Y% c #7F7F7F",
"Z% c #7F7E7E",
"`% c #7E7D7E",
" & c #1DDB1D",
".& c #1BDA1C",
"+& c #8D8C8C",
"@& c #8B8A8A",
"#& c #8A8A89",
"$& c #878786",
"%& c #838382",
"&& c #7E7E7E",
"*& c #7E7D7D",
"=& c #7C7C7D",
"-& c #8A8B8B",
";& c #888988",
">& c #888787",
",& c #868685",
"'& c #7E7E7F",
")& c #7D7E7E",
"!& c #7D7D7D",
"~& c #7C7C7C",
"{& c #7B7B7B",
"]& c #1CDB1B",
"^& c #878687",
"/& c #848384",
"(& c #808081",
"_& c #7D7D7C",
":& c #7C7C7B",
"<& c #7A797A",
"[& c #257225",
"}& c #868787",
"|& c #838484",
"1& c #828382",
"2& c #808181",
"3& c #807F7F",
"4& c #7E7F7E",
"5& c #7D7C7D",
"6& c #7A7B7B",
"7& c #797A7A",
"8& c #797979",
"9& c #848383",
"0& c #828181",
"a& c #818081",
"b& c #7C7D7D",
"c& c #7B7C7C",
"d& c #7A7A7A",
"e& c #79797A",
"f& c #787878",
"g& c #7D7D7E",
"h& c #7B7C7B",
"i& c #787979",
"j& c #828281",
"k& c #807F80",
"l& c #7B7B7A",
"m& c #04FD04",
"n& c #818180",
"o& c #7E7E7D",
"p& c #7D7C7C",
"q& c #7D7E7D",
"r& c #7F7E7F",
"s& c #7C7D7C",
"t& c #7C7B7C",
"u& c #7B7B7C",
"v& c #7C7B7B",
"w& c #7B7A7B",
"x& c #797978",
"y& c #797878",
"z& c #021902",
"A& c #00BD00",
"B& c #00CF00",
"C& c #009700",
"D& c #00D000",
"E& c #00DC00",
"F& c #00E500",
"G& c #00F500",
"H& c #00A400",
"I& c #00B400",
"J& c #00E400",
"K& c #00F900",
"L& c #00B100",
"M& c #00C400",
"N& c #009600",
"O& c #00E600",
"P& c #00B000",
"Q& c #00B800",
"R& c #00C300",
"S& c #00B300",
"T& c #009500",
"U& c #00E100",
"V& c #00BB00",
"W& c #00F800",
"X& c #009B00",
"Y& c #009A00",
" ",
" ",
" ",
" ",
" ",
" . + @ # $ # ",
" % . & * = = $ - ; > , ",
" ' ) ! ~ ~ $ & { ] ^ / ( _ : < ~ ",
" [ } , # # # | ! - 1 + 2 3 4 5 5 5 5 5 6 * ",
" [ } # , , , , # # 7 8 [ 3 9 0 a a a 5 5 5 5 5 5 b * ",
" c ^ 7 | & 7 & $ = d $ @ e f 4 g g h i a 5 5 5 5 5 5 5 5 5 5 b * ",
" j } , ! - - , = k k $ @ e l m 9 n o h 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" 1 7 p q 1 , r k d s / t u v w x y z 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" 8 A B | C r ~ D < E F G H I J 0 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" K K 1 ~ d C $ { . e L M N O J 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" P . ! * = = # > A P ' Q R S T 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ( A , ~ ~ , 7 { } A + ' U V W 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" e B # # # , & ! s D < E G n a 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ; , , # $ ! A 2 N X 0 0 0 a 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" A 7 Y Z ` T .z ..5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.+.@...5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.. g 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 $.%.&.*.*.*.*.*.*.*.*.*.*.*.=.-.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 $.;.;.;.;.;.;.;.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 -.;.;.;.;.;.;.;.;.;.;.;.;.*.>.,.'.'.'.).).).!.!.*.*.*.*.*.*.$.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 ;.;.;.;.;.;.;.;.;.;.~.{.].^././././.>.'.'.'.'.).).).!.!.(._._.*.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 ;.;.;.;.;.;.;.;.:.<.[.}.|.1.2.3.4.5././././.>.'.'.'.6.).).!.!.!._._._.*.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ ;.;.;.;.;.;.7.8.9.0.7.a.b.c.[.d.e.f.g.h.i.j./././.>.'.'.k.).).l.!.!.!._._.m.m.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.;.;.n.0.o.o.p.p.q.r.o.8.a.b.<.1.s.t.].u.i.v./././.'.'.'.).).).!.!.!._._.w.m.m.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.;.x.y.o.q.p.z.A.B.A.C.D.E.F.G.:.H.I.s.J.K.5.L.M./././.'.'.).).).!.!.!._._.N.m.m.O.*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.;.}.P.Q.8.R.C.B.S.S.T.S.S.U.C.V.o.x.<.}.W.~.g.X.Y.Z.`./././.'. +).)..+!.!._._._.m.m.O.++*.*.%.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.s.I.@+x.9.o.A.S.T.#+$+$+%+&+*+=+D.R.7.x.<.d.t.{.4.i.j.-+;+/././.>+).)..+!.!._._._.m.m.m.++*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.;.W.}.P.7.o.C.,+*+$+'+)+)+!+~+$+{+,+p.o.n.c.}.s.~.]+^+/+Z.(+_+/././.).).).!.!.:+_._.m.m.m.++++*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.;.<+P.9.E.A.{+[+}+|+1+1+1+)+2+3+S.A.o.y.P.}.4+~.].^.j.v.(+5+6+/././.).).!.!.(._._.m.m.m.++++++*.*.7+5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.x.o.q.B.*+$+8+1+9+0+a+b+}+$+T.A.o.8.x.}.1.t.].c+j.v.d+e+f+g+/././.).!.!.!._._.m.m.m.++++++h+*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.x.0.p.i+*+2+j+1+0+k+a+1+}+$+l+A.p.7.:.H.1.~.].u.m+n+o+p+q+r+/././.).!.!.s+_._.w.m.m.++++++h+*.*.*.5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.t+p.A.*+u+)+1+a+v+a+w+!+#+*+A.p.7.x+y+1.z+A+u.j.B+C+D+q+g+E+/././.!.!.!._._.F+m.m.++++++h+h+*.*.&.5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ;.;.;.V.C.G+[+H+|+1+1+I+|+'+*+S.A.V.7.:.}.J+~.]+5.j.n+(+K+L+g+M+N+/././.!.(._._.m.m.m.++++++h+h+h+*.*.5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.;.;.;.O+S.*+$+}+P+)+j+'+&+G+i+Q+o.R+<.}.S+~.4.u.j.B+(+K+f+T+M+U+V+/./.!.W+_._.m.m.m.++++++h+h+X+*.*.*.5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ ;.;.R.A.=+T.#+$+$+$+[+T.S.Q+r.7.x.H.1.s.{.]+5.Y+-+Z+K+f+`+M+ @V+/././.!._._.m.m.m.++++.@h+h++@X+*.*.5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ ;.;.;.p.A.,+G+G+@@*+#@B.$@%@8.Q.x+}.S+f.].4.&@v.*@;+q+f+`+=@-@;@>@/././._._.m.m.m.++++,@h+h+'@X+*.*.*.5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.;.;.F.p.Q+D.A.U.,+A.p.R.o.y.x+H.d.s.~.]+5.)@M.(+p+f+g+!@~@-@{@]@/././._._.m.m.^@++++/@h+h+X+X+X+*.*.5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.;.;.;.9.o.o.p.p.r.V.o.8.Q.x.(@d.J+~.].^.m+v.`.Z+K+f+_@M+:@<@[@}@|@/././.N.m.m.1@++++h+h+h+X+X+2@*.*.*.5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 ;.;.x.a.7.7.9.8.7.n.x.<.H.|.S+f.].4.5.3@4@C+p+q+5@`+M+-@6@[@7@8@9@/./.m.m.m.++++++h+h+h+X+X+2@0@*.*.5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 a@;.;.<.x.b.x.x.P.b.@+}.1.S+t.b@K.5.j.v.`.c@K+f+g+M+:@-@d@e@f@g@h@/././.m.m.++++++h+h+X+X+X+X+0@*.*.*.5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 ;.;.|.}.@+}.[.<+i@|.W.s.t.3.K.5.m+L.-+(+_+f+5@`+j@-@V+k@l@8@m@n@o@/./.m.m.++++/@h+h+X+X+X+0@0@0@*.*.5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 ;.;.;.1.1.1.1.1.J+s.~.~.].4.p@q@L.-+(+p+K+f+_@E+:@r@[@e@l@g@n@s@t@/././.++++++h+h+h+X+X+X+0@0@0@*.*.*.5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 ;.;.t.s.t.t.u@~.b@].K.4.5.j.v.v.(+;+5+f+v@E+w@x@V+[@}@|@g@y@z@A@/././.++++++h+h+B@X+X+C@0@0@D@E@*.*.5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 ;.;.;.].].g.].A+h.c+5.m+/+v.-+C+Z+K+F@5@`+M+G@H@[@e@l@I@J@s@K@L@M@/./.++++,@h+h++@X+X+N@0@0@E@E@*.*.O@5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 ;.;.4.u.4.p@^.i.i.j.P@-+-+(+p+K+F@g+Q@M+:@r@;@R@7@8@g@n@o@S@T@U@/././.++h+h+h+X+X+X+0@0@0@E@E@E@*.*.5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 ;.;.j.V@j.j.)@Y+v.-+-+o+Z+e+K+f+g+T+W@:@-@V+k@e@X@g@n@Y@Z@L@M@`@ #/./.++h+h+.#X+X++#0@0@@#E@E@##*.*.-.5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 O@;.;.v.B+M.n+-+*@(+;+p+D+6+$#g+`+M+:@-@V+[@e@%#&#*#=#o@L@-#U@;#>#/./.h+h+h+X+X+X+0@0@0@E@E@E@,#*.*.*.5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 ;.;.C+(+(+(+(+c@p+K+L+f+g+T+'#)#:@-@H@d@!#l@&#~#{#Y@]#L@-#`@^#/#(#/./.h+h+X+X+X+0@0@0@E@E@_#,#,#*.*.5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 ;.;.;.p+p+e+K+K+q+f+:#r+`+E+M+N+-@V+[@e@l@8@g@n@<#[#L@-#`@}#|#(#1#/./.h+X+X+X+2#0@0@3#E@E@4#,#,#*.*.&.5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 $.;.;.L+F@q+$#5#g+6#Q@`+M+:@-@7#6@k@e@8#9#m@n@s@]#0#a#`@;#>#b#c#d#/./.X+X+X+N@0@0@0@E@E@E@,#,#,#e#*.*.5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 ;.;.g+v@v@`+`+'#E+w@:@f#7#V+[@g#e@l@&#g@n@s@o@h#L@-#;#i#j#(#k#l#m#/./.X+X+2#0@0@n#E@E@,#,#,#o#e#*.*.-.5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 ;.;.;.!@M+M+j@~@N+f#p#V+q#[@e@r#8#s#t#n@s@o@A@L@U@`@ #/#j#u#v#w#x#/./.X+2#0@0@y#E@E@E@,#,#,#e#e#*.*.*.5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 $.;.;.:@:@f#-@-@p#V+6@[@k@z#8@8@g@m@s@Y@K@h#L@A#B#^#C#D#k#E#F#G#H#/./.X+0@0@0@E@E@E@I#,#,#J#e#e#K#*.*.5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 ;.;.V+L#p#V+M#[@>@e@7@l@X@N#m@n@s@o@t@A@O#P#Q#R#S#T#1#U#V#G#H#W#/././.0@0@X#E@E@E@,#,#,#e#e#e#Y#*.*.$.5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 ;.;.[@[@Z#Z#>@e@z#%#|@8@g@n@{#s@`#S@L@O#-#Q# $C#T#.$k#V#m#x#W#+$@$/./.0@0@E@E@E@,#,#,#o#e#e##$Y#*.*.*.5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 &.;.;.e@7@l@X@8@9#N#t#n@n@s@<#t@$$L@O#`@B#%$&$j#(#*$v#m#x#H#=$-$;$/./.0@E@E@E@_#,#,#,#e#e#e#Y#Y#Y#*.*.5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 ;.;.8@8@8@>$g@9@n@=#s@Y@o@A@0#,$-#`@R#>#&$'$k#*$)$!$x#~$=$@$;${$/./.0@E@E@E@,#,#,#o#e#e#Y#Y#Y#]$*.*.-.5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 ;.;.n@9@n@{#h@y@z@`#]#A@^$L@O#/$($R#>#j#(#u#E#V#G#_$:$=$-$;${$<$/././.E@E@,#,#,#[$e#e#e#Y#Y#Y#]$*.*.*.5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 ;.;.;.s@s@<#}$o@t@A@^$L@-#|$`@R#%$|#j#1$k#d#F#G#G#2$+$3$4${$5$6$7$/./.E@_#,#,#,#e#e#e#8$Y#Y#9$]$]$*.*.5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 %.;.;.A@S@A@0#0$L@L@|$-#`@;# $>#a$(#.$k#v#V#b$c$W#d$e$f$g$h$i$j$k$/./.##,#,#,#e#e#e#l$Y#Y#Y#]$]$]$*.*.-.b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 ;.;.0$a#-#M@-#A#`@m$B#^#>#/#j#n$1#v#)$V#G#x#W#+$3$o$p$q$i$i$r$s$/./.,#,#,#t$e#e#e#Y#Y#Y#]$]$]$u$*.*.*.b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 ;.;.P#P#`@m$`@R# #>#>#j#'$(#k#v#v#F#m#G#H#W#+$v$w${$x$y$z$A$B$C$/./.,#,#[$e#e#e#K#Y#Y#D$]$]$]$E$E$*.*.b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 ;.;.;.R#R#^#%$&$S#j#(#.$u#F$v#G$V#G#H#W#d$3$@$;${$h$H$7$I$J$C$K$/././.,#e#e#e#8$Y#Y#Y#]$]$]$E$E$E$*.*.b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 %.;.;.&$a$j#T#j#(#c#k#E#v#L$M$G#x#N$O$+$-$P$p${$Q$i$j$R$B$S$T$U$V$/./.e#e#e#e#Y#Y#Y#]$]$]$W$E$E$E$*.*.X$* ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 ;.;.'$(#(#Y$F$*$v#F#F#b$G#c$Z$N$+$`$4$f$ %x$.%i$A$k$B$C$K$U$+%@%/./.e#e#l$Y#Y#Y##%]$]$W$E$E$E$$%$%*.= * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 ;.;.%%E#E#v#L$L$V#G#_$_$Z$2$O$+$e$;$&%{$<$Q$*%I$=%B$C$-%U$V$@%;%/./.e#e#Y#Y#Y#>%]$]$]$E$E$E$,%$%$%*.= * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 ;.;.V#V#!$!$G#_$H#H#Z$W#'%3$@$f$&%&%h$y$z$j$)%=%!%C$K$U$V$~%{%]%/./.e#Y#Y#Y#Y#]$]$]$^%E$E$/%$%$%$%*.= (% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 ;.;.;.G#H#H#:$Z$W#W#+$-$@$P$_%{$<$x$H$i$j$k$B$:%<%K$U$V$;%{%]%[%/./.Y#Y#Y#Y#]$]$]$W$E$E$E$$%$%$%}%*.= |% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 $.;.;.W#W#1%'%+$`$@$4$;$;${$x$x$Q$j$j$k$2%:%C$T$U$U$3%4%{%]%[%5%/./.Y#Y#Y#]$]$]$u$E$E$E$$%$%$%6%7%7%= |% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 ;.;.`$-$8%@$o$;$&%{$<$9%x$i$0%j$A$s$B$C$<%a%U$V$b%{%c%]%[%d%e%f%/./.Y#]$]$]$^%E$E$E$g%$%$%$%7%7%7%= |% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 ;.;.;$;$&% %{${$5$x$i$z$j$j$)%k$B$:%C$K$h%V$3%@%i%j%k%l%m%n%o%p%/./.]$]$]$]$E$E$E$q%$%$%$%7%7%7%r%= |% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 ;.;.h$h$5$x$x$Q$i$0%7$j$k$J$B$C$C$K$K$U$V$b%s%{%]%[%t%u%e%v%p%w%/./.]$]$]$E$E$E$/%$%$%$%x%7%7%7%y%= |%z% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 ;.;.y$H$i$i$j$j$r$k$=%J$A%!%B%K$C%U$V$b%4%{%D%[%[%5%e%f%o%E%F%G%/./.]$]$E$E$E$q%$%$%$%x%7%7%7%H%y%I%|%J% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 ;.;.;.r$A$R$J$k$B$B$:%C$K$a%U$U$V$K%4%{%{%]%[%L%M%n%N%o%O%w%P%Q%/./.W$E$E$E$,%$%$%$%$%7%7%7%R%y%y%I%|%J% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 $.;.;.2%B$B$B$S%C$B%K$h%U$T%V$K%@%i%c%]%U%V%5%e%f%o%W%X%G%Y%Z%`%/./.E$E$E$E$$%$%$% &7%7%7%.&y%y%y%I%|%J% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.C$C$-%+&a%h%U$+%@&#&@%i%i%D%$&$&[%5%m%f%%&p%O%F%Y%Y%&&*&=&/./.E$E$q%$%$%$%6%7%7%7%.&y%y%y%y%I%|%J% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.h%h%U$U$-&V$@%#&;&s%{%>&]%U%,&5%e%e%%&o%p%X%G%P%'&)&!&~&{&/./.E$$%$%$%$% &7%7%7%]&y%y%y%y%y%I%|%J% ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.V$3%~%@%@%@%;&{%]%^&[%[%L%5%e%/&f%N%W%X%(&G%Y%&&!&_&:&{&<&/./.,%$%$%$%x%7%7%7%R%y%y%y%y%y%y%I%[&J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.{%{%s%{%{%c%^&}&[%V%5%M%e%|&f%1&p%X%2&3&Y%4&`%5&~&{&6&7&8&/./.$%$%$%7%7%7%7%R%y%y%y%y%y%y%y%I%[&J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.]%$&k%}&[%[%L%5%5%e%|&9&f%p%E%0&a&G%Y%Q%&&!&b&c&{&d&e&f&f&/./.$%$%7%7%7%7%R%y%y%y%y%y%y%y%y%I%[&J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.[%t%L%5%M%d%e%|&f%f%1&p%X%X%G%G%Y%Q%&&g&!&~&h&d&7&i&;.;.;.;.;.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.= [&J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.M%e%|&|&n%f%f%%&j&O%X%a&G%k&Y%Q%*&*&b&~&{&l&;.;.;.;.;.;.;.;.;.*.*.*.*.*.7+m&O@*.*.*.*.*.*.*.= |%J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.f%f%1&p%p%X%X%n&n&G%G%Y%4&&&o&!&p&~&{&;.;.;.;.;.;.;.;.$.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -.X$|%J%;. ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.X%X%X%2&G%G%G%k&Y%4&Q%)&!&!&~&~&;.;.;.;.;.;.;.$.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.G%G%k&P%Y%Y%Z%&&o&q&!&=&~&;.;.;.;.;.;.;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.r&r&&&&&&&o&!&~&s&t&:&;.;.;.;.;.;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.!&b&!&5&~&~&{&{&;.;.;.;.;.;.-.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.u&v&{&{&{&l&;.;.;.;.;.;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.w&d&d&7&;.;.;.;.;.%.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.x&y&;.;.;.;.;.-.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.;.;.;.;.;.-.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.;.;.;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 ;.;.;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 z&;.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.^ #.5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.) h 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" A D A&B&x T a 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" ; ~ r ! C&U D&O E&9 z 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" | > s # d k d > 6 f F&n J G&0 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" H&} , | & & # * d 7 ) I&J&z h K&0 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" e D # , , , , # s + L&E&5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" c K & # # , 7 > 1 A Y M&o 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" N&s $ * $ & 1 A K 6 U w 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" P ; & = = $ { . ' j t M&O&0 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" . ) > * C r # @ 6 P&Q&R&I g 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" } } s d k d s P S&Z D&x .5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" +.& > D { ~ r r s T&M v E&U&` i 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 b * ",
" 6 7 & - s # C k $ } 2 H 4 ` o z 0 5 5 5 5 5 5 5 5 5 5 b * ",
" H&@ # & & | $ * = - T&V&O&h W&i W 5 5 5 5 5 5 b * ",
" X&s , , , , , | 7 } j Z G&5 5 5 5 5 b * ",
" H&) & $ $ $ & > 1 8 Y&R F&5 ( * ",
" 6 } $ ~ * # p +.C&p , ",
" C&+ 7 = d ~ , ",
" ; ^ 1 ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};

View File

@@ -0,0 +1,41 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
class SurfWorkbench ( Workbench ):
""" @brief Workbench of Ship design module. Here toolbars & icons are append. """
from surfUtils import Paths, Translator
import SurfGui
Icon = Paths.iconsPath() + "/Ico.png"
MenuText = str(Translator.translate("Surface tools"))
ToolTip = str(Translator.translate("Surface tools"))
def Initialize(self):
# ToolBar
list = ["Surf_IsoCurve", "Surf_SliceCurve", "Surf_Border", "Surf_Convert"]
self.appendToolbar("Surface tools",list)
# Menu
list = ["Surf_IsoCurve", "Surf_SliceCurve", "Surf_Border", "Surf_Convert"]
self.appendMenu("Surface tools",list)
Gui.addWorkbench(SurfWorkbench())

View File

@@ -0,0 +1,52 @@
# Change data dir from default ($(prefix)/share) to actual dir
datadir = $(prefix)/Mod/Surfaces
data_DATA = InitGui.py \
SurfGui.py
nobase_data_DATA = \
Icons/BorderIco.png \
Icons/BorderIco.xcf \
Icons/BorderIco.xpm \
Icons/ConvertIco.png \
Icons/ConvertIco.xcf \
Icons/ConvertTo4SidesIco.xpm \
Icons/Ico.png \
Icons/Ico.xcf \
Icons/Ico.xpm \
Icons/IsoCurveIco.png \
Icons/IsoCurveIco.xcf \
Icons/IsoCurveIco.xpm \
Icons/SliceIco.png \
Icons/SliceIco.xcf \
Icons/SliceIco.xpm \
surfBorder/__init__.py \
surfConvert/__init__.py \
surfConvert/Preview.py \
surfConvert/TaskPanel.py \
surfConvert/TaskPanel.ui \
surfISOCurve/__init__.py \
surfISOCurve/PointTracker.py \
surfISOCurve/Preview.py \
surfISOCurve/TaskPanel.py \
surfISOCurve/TaskPanel.ui \
surfSlice/__init__.py \
surfSlice/PointTracker.py \
surfSlice/Preview.py \
surfSlice/TaskPanel.py \
surfSlice/TaskPanel.ui \
surfUtils/Geometry.py \
surfUtils/__init__.py \
surfUtils/Math.py \
surfUtils/Paths.py \
surfUtils/Translator.py
CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = \
$(data_DATA) \
$(nobase_data_DATA) \
CMakeLists.txt \
README \
surfaces.dox

11
src/Mod/Surfaces/README Normal file
View File

@@ -0,0 +1,11 @@
* Authors
---------
Jose Luis Cercós Pita <jlcercos@gmail.com>
Alicia Lapique <a.lapique@alumnos.upm.es>
* Introduction
--------------
Surfaces is a module to work with surfaces, providing GUI for tools implemented at python API, and more complex tools.

View File

@@ -0,0 +1,78 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
from PyQt4 import QtCore, QtGui
import FreeCAD, FreeCADGui, os
class IsoCurve:
def Activated(self):
import surfISOCurve
surfISOCurve.load()
def GetResources(self):
from surfUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/IsoCurveIco.png"
MenuText = str(Translator.translate('Get ISO curve'))
ToolTip = str(Translator.translate('Get ISO curve from surface'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class SliceCurve:
def Activated(self):
import surfSlice
surfSlice.load()
def GetResources(self):
from surfUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/SliceIco.png"
MenuText = str(Translator.translate('Get surface slice'))
ToolTip = str(Translator.translate('Get surface intersection with coordinates planes'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class Border:
def Activated(self):
import surfBorder
surfBorder.load()
def GetResources(self):
from surfUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/BorderIco.png"
MenuText = str(Translator.translate('Get border'))
ToolTip = str(Translator.translate('Get edges from objects'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class Convert:
def Activated(self):
import surfConvert
surfConvert.load()
def GetResources(self):
from surfUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/ConvertIco.png"
MenuText = str(Translator.translate('Convert to 4 sides surface'))
ToolTip = str(Translator.translate('Convert a surface (or couple of them) into 4 sides surface'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
FreeCADGui.addCommand('Surf_IsoCurve', IsoCurve())
FreeCADGui.addCommand('Surf_SliceCurve', SliceCurve())
FreeCADGui.addCommand('Surf_Border', Border())
FreeCADGui.addCommand('Surf_Convert', Convert())

View File

@@ -0,0 +1,51 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
from surfUtils import Geometry, Translator
def load():
""" Loads the tool. Getting the border don't require any
option, so can be executed directly without any task panel. """
edges = Geometry.getBorders()
if not edges:
wrn = Translator.translate("Can't get any edge from selected objects")
FreeCAD.Console.PrintWarning(wrn)
return
obj = edges[0]
for i in range(0,len(edges)):
obj = obj.oldFuse(edges[i])
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
obj = objs[len(objs)-1]
obj.Label = 'Border'

View File

@@ -0,0 +1,82 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCADShip modules
from surfUtils import Paths
from surfUtils import Geometry
from surfUtils import Math
class Preview(object):
def __init__(self,U,V):
""" Constructor.
@param U Part::topoShape object that contains the U direction edge.
@param V Part::topoShape object that contains the V direction edge.
"""
self.objU = None
self.objV = None
self.U = U
self.V = V
self.buildObjs()
self.setProperties()
def buildObjs(self):
""" Builds objects to show.
"""
Part.show(self.U)
objs = FreeCAD.ActiveDocument.Objects
self.objU = objs[len(objs)-1]
Part.show(self.V)
objs = FreeCAD.ActiveDocument.Objects
self.objV = objs[len(objs)-1]
def setProperties(self):
""" Set colour of lines and width.
"""
self.objU.Label = 'U direction'
self.objV.Label = 'V direction'
# Get GUI objects instance
objU = FreeCADGui.ActiveDocument.getObject(self.objU.Name)
objV = FreeCADGui.ActiveDocument.getObject(self.objV.Name)
objU.LineColor = (0.0,0.0,1.0)
objU.LineWidth = 5.00
objV.LineColor = (1.0,0.0,0.0)
objV.LineWidth = 5.00
def clean(self,Destroy=True):
""" Erase all sections from screen.
@param self Auto call object.
@param Destroy True if the object must be destroyed, False otherwise.
"""
if (not self.objU) or (not self.objV):
return
FreeCADGui.ActiveDocument.hide(self.objU.Name)
FreeCADGui.ActiveDocument.hide(self.objV.Name)
if Destroy:
FreeCAD.ActiveDocument.removeObject(self.objU.Name)
FreeCAD.ActiveDocument.removeObject(self.objV.Name)
self.objU=None
self.objV=None

View File

@@ -0,0 +1,637 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# Standart libraries
import math
# Import FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Import Qt libraries
from PyQt4 import QtGui,QtCore
# Import surface module utils
from surfUtils import Paths, Geometry, Math, Translator
# Import tool utils
import Preview
class TaskPanel:
def __init__(self):
""" Class constructor, that loads the user interface and set
minimum data as empty values.
"""
self.ui = Paths.modulePath() + "/surfConvert/TaskPanel.ui"
self.objs = []
self.edges = []
self.faces = []
self.surf = None
self.preview = None
def accept(self):
""" Method called when accept button is clicked.
@return True if all gone right, False otherwise.
"""
if not self.surf:
return False
App.Part.show(self.surf.toShape())
objs = App.ActiveDocument.Objects
obj = objs[len(objs)-1]
obj.Label = 'Surface'
self.preview.clean()
return True
def reject(self):
""" Method called when cancel button is clicked.
@return True if all gone right, False otherwise.
"""
if self.preview :
self.preview.clean()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
""" Setups the user interface taking and storing all controls.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.nU = form.findChild(QtGui.QSpinBox, "nU")
form.nV = form.findChild(QtGui.QSpinBox, "nV")
form.deg = form.findChild(QtGui.QSpinBox, "deg")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
QtCore.QObject.connect(form.nU, QtCore.SIGNAL("valueChanged(int)"), self.onNUV)
QtCore.QObject.connect(form.nV, QtCore.SIGNAL("valueChanged(int)"), self.onNUV)
QtCore.QObject.connect(form.deg, QtCore.SIGNAL("valueChanged(int)"), self.onNUV)
return False
def getMainWindow(self):
""" returns the main window """
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def initValues(self):
""" Setup initial values. """
# Objects to work
self.objs = Gui.Selection.getSelection()
if not self.objs:
msg = Translator.translate("4 connected edges and at least 1 surface must be selected (Any object has been selected)")
App.Console.PrintError(msg)
return True
if len(self.objs) < 5:
msg = Translator.translate("4 connected edges and at least 1 surface must be selected (Less than 5 objects selected)")
App.Console.PrintError(msg)
return True
# Separate edge objects and face objects to work with them separately.
if self.getEdgesFaces():
return True
# Ensure that closed edges given
if not self.isClosed():
return True
# Sort edges (as connect chain)
if self.sortEdges():
return True
# First surface draft
if self.getPoints():
return True
if self.createSurface():
return True
# On screen data
self.preview = Preview.Preview(self.edges[0],self.edges[1])
msg = Translator.translate("Ready to work\n")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Convert to 4 side surface"))
nUString = Translator.translate("Points at U")
self.form.findChild(QtGui.QLabel, "nULabel").setText("<font color=#0000ff>" + nUString + "</font>")
nVString = Translator.translate("Points at V2")
self.form.findChild(QtGui.QLabel, "nVLabel").setText("<font color=#ff0000>" + nVString + "</font>")
self.form.findChild(QtGui.QLabel, "degLabel").setText(Translator.translate("Surface degree"))
def onNUV(self, value):
""" Answer to nU points or nV points modification events.
@param value Changed value.
"""
if self.getPoints():
return
if self.createSurface():
return
self.form.deg.setMaximum(self.surf.MaxDegree)
def getEdgesFaces(self):
""" Returns two arrays filled with the edges and faces selected.
@return True if error happens. False otherwise
"""
self.edges = []
self.faces = []
for i in range(0,len(self.objs)):
objFaces = Geometry.getFaces(self.objs[i])
if not objFaces:
objEdges = Geometry.getEdges([self.objs[i]])
if not objEdges:
msg = Translator.translate("4 connected edges and at least 1 surface must be selected (Any edge found)")
App.Console.PrintError(msg)
return True
for j in range(0, len(objEdges)):
self.edges.append(objEdges[j])
else:
for j in range(0, len(objFaces)):
self.faces.append(objFaces[j])
if len(self.edges) != 4:
msg = Translator.translate("4 connected edges and at least 1 surface must be selected (More/less edges not allowed)")
App.Console.PrintError(msg)
return True
return False
def isClosed(self):
""" Returns if the edges objects are a closed curve.
@return True if a closed curve can be built with edge objects.
False otherwise
"""
edges = self.edges
for i in range(0,len(edges)):
edge = edges[i]
vertex1 = edge.Vertexes
count = [0,0]
for j in range(0,len(edges)):
if j== i:
continue
vertex2 = edges[j].Vertexes
for k in range(0,2):
if Math.isSameVertex(vertex1[0],vertex2[k]):
count[0] = count[0]+1
if Math.isSameVertex(vertex1[1],vertex2[k]):
count[1] = count[1]+1
if count != [1,1]:
msg = Translator.translate("4 Edges curve must be closed")
App.Console.PrintError(msg)
return False
return True
def sortEdges(self):
""" Sort the edges by their connection points. Also gives if
an edge is ill oriented (thir connection point is the end
point, not the starting point), with True when is good oriented,
and False otherwise.
@return True if error happens. False otherwise
"""
edges = self.edges
self.edges = [edges[0]]
self.direction = [True]
Vertex = self.edges[0].Vertexes[1]
for i in range(0,len(edges)-1):
for j in range(0,len(edges)):
if self.edges[i] == edges[j]:
continue
Vertexes = edges[j].Vertexes
if Math.isSameVertex(Vertex,Vertexes[0]):
Vertex = Vertexes[1]
self.edges.append(edges[j])
self.direction.append(True)
break
if Math.isSameVertex(Vertex,Vertexes[1]):
Vertex = Vertexes[0]
self.edges.append(edges[j])
self.direction.append(False)
break
return False
def getPoints(self):
""" Get points that will make the surface.
@return True if error happens. False otherwise.
"""
# Discretize the edges using nU,nV
if self.divideEdges():
return True
if self.samplePoints():
return True
if self.getSurfacePoints():
return True
while self.redistributePointsU():
continue
while self.redistributePointsV():
continue
return False
def divideEdges(self):
""" Get points along the edges. This method only divide the
edges into nU/nV parametrically equidistant points.
@return True if error happens. False otherwise.
"""
# Get curves from edges
curves=[]
for i in range(0,len(self.edges)):
curves.append(self.edges[i].Curve)
# Get number of divisions at U,V
nU = self.form.nU.value()
nV = self.form.nV.value()
# Get points at U direction (length parameter will used)
vertexes = self.edges[0].Vertexes
u = curves[0].parameter(App.Base.Vector(vertexes[0].X, vertexes[0].Y, vertexes[0].Z))
uEnd = curves[0].parameter(App.Base.Vector(vertexes[1].X, vertexes[1].Y, vertexes[1].Z))
du = (uEnd - u) / (nU-1.0)
Points0=[]
for i in range(0, nU):
knots = curves[0].KnotSequence
point0 = curves[0].value(u)
Points0.append(point0)
u = u + du
vertexes = self.edges[2].Vertexes
u = curves[2].parameter(App.Base.Vector(vertexes[1].X, vertexes[1].Y, vertexes[1].Z))
uEnd = curves[2].parameter(App.Base.Vector(vertexes[0].X, vertexes[0].Y, vertexes[0].Z))
du = (uEnd - u) / (nU-1.0)
Points2=[]
for i in range(0, nU):
knots = curves[2].KnotSequence
point2 = curves[2].value(u)
Points2.append(point2)
u = u + du
# Get points at V direction (length parameter will used)
vertexes = self.edges[1].Vertexes
v = curves[1].parameter(App.Base.Vector(vertexes[0].X, vertexes[0].Y, vertexes[0].Z))
vEnd = curves[1].parameter(App.Base.Vector(vertexes[1].X, vertexes[1].Y, vertexes[1].Z))
dv = (vEnd - v) / (nV-1.0)
Points1=[]
for i in range(0, nV):
knots = curves[1].KnotSequence
point1 = curves[1].value(v)
Points1.append(point1)
v = v + dv
vertexes = self.edges[3].Vertexes
v = curves[3].parameter(App.Base.Vector(vertexes[1].X, vertexes[1].Y, vertexes[1].Z))
vEnd = curves[3].parameter(App.Base.Vector(vertexes[0].X, vertexes[0].Y, vertexes[0].Z))
dv = (vEnd - v) / (nV-1.0)
Points3=[]
for i in range(0, nV):
knots = curves[3].KnotSequence
point3 = curves[3].value(v)
Points3.append(point3)
v = v + dv
# Store points arrays
self.EdgePoints=[Points0,Points1,Points2,Points3]
# Ensure that is good oriented
for i in range(0,4):
if not self.direction[i]:
self.EdgePoints[i].reverse()
return False
def samplePoints(self):
""" Builds a set of points between the edges points. The points
are a smooth interpolation between edges points in order to
project it over the surface.
@return True if error happens. False otherwise.
"""
# We will advance in V direction, getting point columns, so two
# points columns are knowed from U starting and end curves
startU = self.EdgePoints[0]
endU = self.EdgePoints[2]
endV = self.EdgePoints[1]
startV = self.EdgePoints[3]
self.sample = [startU]
# Take two guides from the starting and end U curves. All
# sample points will be interpolated with this guides
Guide0 = startU[len(startU)-1] - startU[0]
Length0 = Guide0.Length
Guide0.normalize()
Guide1 = endU[len(endU)-1] - endU[0]
Length1 = Guide1.Length
Guide1.normalize()
# Loop over columns
for i in range(1,len(startV)-1):
# Get the guide
Guide = endV[i] - startV[i]
Length = Guide.Length
Guide.normalize()
# Loop over points of the column
points = []
points.append(startV[i])
for j in range(1,len(startU)-1):
# Get deviation at starting U
v0 = (startU[j] - startU[0]).multiply(1.0 / Length0) - Guide0
# Get deviation at ending U
v1 = (endU[j] - endU[0]).multiply(1.0 / Length1) - Guide1
# Get factor
factor = float(i) / len(startV)
# Interpolate
v = (v0.multiply(1.0-factor) + v1.multiply(factor) + Guide).multiply(Length)
points.append(startV[i]+v)
points.append(endV[i])
self.sample.append(points)
# Append last points column (end U curve)
self.sample.append(endU)
return False
def getSurfacePoints(self):
""" Get the points of the surface. Here sample points will be
projected into the surface, getting another surface with nU,nV
knots.
@todo Support trimmed surfaces.
@return True if error happens. False otherwise.
"""
surf = self.faces[0].Surface
self.uv=[]
self.points=[]
self.surfacesID=[]
for j in range(0,len(self.sample)):
points=[]
uv=[]
surfacesID=[]
for k in range(0,len(self.sample[j])):
UV = surf.parameter(self.sample[j][k])
umax = surf.UKnotSequence[len(surf.UKnotSequence)-1]
umin = surf.UKnotSequence[0]
vmax = surf.VKnotSequence[len(surf.VKnotSequence)-1]
vmin = surf.VKnotSequence[0]
uv.append([UV[0],UV[1]])
uv[k][0] = max(min(uv[k][0],umax), umin)
uv[k][1] = max(min(uv[k][1],vmax), vmin)
point = surf.value(uv[k][0], uv[k][1])
points.append(point)
surfacesID.append(0)
self.uv.append(uv)
self.points.append(points)
self.surfacesID.append(surfacesID)
for i in range(1,len(self.faces)):
surf = self.faces[i].Surface
for j in range(0,len(self.sample)):
for k in range(0,len(self.sample[j])):
UV = surf.parameter(self.sample[j][k])
uv = [UV[0],UV[1]]
UV = uv[:]
umax = surf.UKnotSequence[len(surf.UKnotSequence)-1]
umin = surf.UKnotSequence[0]
vmax = surf.VKnotSequence[len(surf.VKnotSequence)-1]
vmin = surf.VKnotSequence[0]
UV[0] = uv[0]/(surf.UKnotSequence[len(surf.UKnotSequence)-1])
UV[1] = uv[1]/(surf.VKnotSequence[len(surf.VKnotSequence)-1])
ru=abs(UV[0]-0.5)
rv=abs(UV[1]-0.5)
surf2 = self.faces[self.surfacesID[j][k]].Surface
UV2 = surf2.parameter(self.sample[j][k])
uv2 = [UV2[0],UV2[1]]
UV2 = uv2[:]
umax2 = surf2.UKnotSequence[len(surf2.UKnotSequence)-1]
umin2 = surf2.UKnotSequence[0]
vmax2 = surf2.VKnotSequence[len(surf2.VKnotSequence)-1]
vmin2 = surf2.VKnotSequence[0]
UV2[0] = uv2[0]/(surf2.UKnotSequence[len(surf2.UKnotSequence)-1])
UV2[1] = uv2[1]/(surf2.VKnotSequence[len(surf2.VKnotSequence)-1])
ru2=abs(UV2[0]-0.5)
rv2=abs(UV2[1]-0.5)
point=surf.value(UV[0],UV[1])
point2=surf2.value(UV2[0],UV2[1])
dif= math.sqrt((point[0]-self.sample[j][k][0])**2+(point[1]-self.sample[j][k][1])**2+(point[2]-self.sample[j][k][2])**2)
dif2= math.sqrt((point2[0]-self.sample[j][k][0])**2+(point2[1]-self.sample[j][k][1])**2+(point2[2]-self.sample[j][k][2])**2)
nU = len(self.points)
nV = len(self.points[j])
deltaU = 1/(2*nU)
deltaV = 1/(2*nV)
if ((ru < deltaU) and (rv < deltaV)):
uv[0] = max(min(uv[0],umax), umin)
uv[1] = max(min(uv[1],vmax), vmin)
self.uv[j][k]=uv
point = surf.value(uv[0], uv[1])
self.points[j][k]=point
self.surfacesID[j][k] = i
elif (dif2 > dif):
uv[0] = max(min(uv[0],umax), umin)
uv[1] = max(min(uv[1],vmax), vmin)
self.uv[j][k]=uv
point = surf.value(uv[0], uv[1])
self.points[j][k]=point
self.surfacesID[j][k] = i
return False
def redistributePointsU(self):
""" Redistributes the points of the surface (U direction).
@return False if all points are right placed. True otherwise.
"""
#Redistribute columns
for i in range(0,len(self.points)):
sumdif=0.0
difs=[]
# Compute distances between points
for j in range(1,len(self.points[i])):
vdif=self.points[i][j]-self.points[i][j-1]
dif=vdif.Length
sumdif=sumdif+dif
difs.append(dif)
# Loop over point distances
for k in range(0,len(difs)):
# If not the same surface for each point, UV
# redistribution is not valid, so 3D points must be
# edited (more effort and worst convergency).
if self.surfacesID[i][k] != self.surfacesID[i][k+1]:
if difs[k]>=(2*sumdif/len(difs)):
point1 = App.Base.Vector(0.0,0.0,0.0)
point1.x = self.points[i][k][0]+0.33*(self.points[i][k+1][0]-self.points[i][k][0])
point1.y = self.points[i][k][1]+0.33*(self.points[i][k+1][1]-self.points[i][k][1])
point1.z = self.points[i][k][2]+0.33*(self.points[i][k+1][2]-self.points[i][k][2])
point2 = App.Base.Vector(0.0,0.0,0.0)
point2.x = self.points[i][k+1][0]-0.33*(self.points[i][k+1][0]-self.points[i][k][0])
point2.y = self.points[i][k+1][1]-0.33*(self.points[i][k+1][1]-self.points[i][k][1])
point2.z = self.points[i][k+1][2]-0.33*(self.points[i][k+1][2]-self.points[i][k][2])
moved = False
if(k != 0):
self.points[i][k] = point1
surf1 = self.faces[self.surfacesID[i][k]].Surface
uv = surf1.parameter(self.points[i][k])
self.uv[i][k] = [uv[0], uv[1]]
self.points[i][k]=surf1.value(self.uv[i][k][0],self.uv[i][k][1])
moved = True
if(k+1 != len(self.points[i])-1):
self.points[i][k+1] = point2
surf2 = self.faces[self.surfacesID[i][k+1]].Surface
uv = surf2.parameter(self.points[i][k+1])
self.uv[i][k+1] = [uv[0], uv[1]]
self.points[i][k+1]=surf2.value(self.uv[i][k+1][0],self.uv[i][k+1][1])
moved = True
if moved:
return True
continue
# If same surface for each point, UV
# redistribution is possible, with better convergency
# and less computation effort.
if difs[k]>=(2*sumdif/len(difs)):
uv1 = [0.0,0.0]
uv1[0] = self.uv[i][k][0]+0.33*(self.uv[i][k+1][0]-self.uv[i][k][0])
uv1[1] = self.uv[i][k][1]+0.33*(self.uv[i][k+1][1]-self.uv[i][k][1])
uv2 = [0.0,0.0]
uv2[0] = self.uv[i][k+1][0]-0.33*(self.uv[i][k+1][0]-self.uv[i][k][0])
uv2[1] = self.uv[i][k+1][1]-0.33*(self.uv[i][k+1][1]-self.uv[i][k][1])
moved = False
if(k != 0):
self.uv[i][k] = uv1[:]
surf = self.faces[self.surfacesID[i][k]].Surface
self.points[i][k] = surf.value(self.uv[i][k][0], self.uv[i][k][1])
moved = True
if(k+1 != len(self.points[i])-1):
self.uv[i][k+1] = uv2[:]
surf = self.faces[self.surfacesID[i][k+1]].Surface
self.points[i][k+1] = surf.value(self.uv[i][k+1][0], self.uv[i][k+1][1])
if moved:
return True
return False
def redistributePointsV(self):
""" Redistributes the points of the surface (V direction).
@return False if all points are right placed. True otherwise.
"""
#Redistribute rows
for i in range(0,len(self.points[0])):
sumdif=0
difs=[]
# Compute distances between points
for j in range(1,len(self.points)):
vdif=self.points[j][i]-self.points[j-1][i]
dif=vdif.Length
sumdif=sumdif+dif
difs.append(dif)
# Loop over point distances
for k in range(0,len(difs)):
# If not the same surface for each point, UV
# redistribution is not valid, so 3D points must be
# edited (more effort and worst convergency).
if self.surfacesID[k][i] != self.surfacesID[k+1][i]:
if difs[k]>=(2*sumdif/len(difs)):
point1 = App.Base.Vector(0.0,0.0,0.0)
point1.x = self.points[k][i][0]+0.33*(self.points[k+1][i][0]-self.points[k][i][0])
point1.y = self.points[k][i][1]+0.33*(self.points[k+1][i][1]-self.points[k][i][1])
point1.z = self.points[k][i][2]+0.33*(self.points[k+1][i][2]-self.points[k][i][2])
point2 = App.Base.Vector(0.0,0.0,0.0)
point2.x = self.points[k+1][i][0]-0.33*(self.points[k+1][i][0]-self.points[k][i][0])
point2.y = self.points[k+1][i][1]-0.33*(self.points[k+1][i][1]-self.points[k][i][1])
point2.z = self.points[k+1][i][2]-0.33*(self.points[k+1][i][2]-self.points[k][i][2])
moved = False
if(k != 0):
self.points[k][i] = point1
surf1 = self.faces[self.surfacesID[k][i]].Surface
uv = surf1.parameter(self.points[k][i])
self.uv[k][i] = [uv[0], uv[1]]
self.points[k][i]=surf1.value(self.uv[k][i][0],self.uv[k][i][1])
moved = True
if(k+1 != len(self.points)-1):
self.points[k+1][i] = point2
surf2 = self.faces[self.surfacesID[k+1][i]].Surface
uv = surf2.parameter(self.points[k+1][i])
self.uv[k+1][i] = [uv[0], uv[1]]
self.points[k+1][i]=surf2.value(self.uv[k+1][i][0],self.uv[k+1][i][1])
moved = True
if moved:
return True
continue
# If same surface for each point, UV
# redistribution is possible, with better convergency
# and less computation effort.
if difs[k]>=(2*sumdif/len(difs)):
uv1 = [0.0,0.0]
uv1[0] = self.uv[k][i][0]+0.33*(self.uv[k+1][i][0]-self.uv[k][i][0])
uv1[1] = self.uv[k][i][1]+0.33*(self.uv[k+1][i][1]-self.uv[k][i][1])
uv2 = [0.0,0.0]
uv2[0] = self.uv[k+1][i][0]-0.33*(self.uv[k+1][i][0]-self.uv[k][i][0])
uv2[1] = self.uv[k+1][i][1]-0.33*(self.uv[k+1][i][1]-self.uv[k][i][1])
moved = False
if(k != 0):
self.uv[i][k] = uv1[:]
surf = self.faces[self.surfacesID[k][i]].Surface
self.points[k][i] = surf.value(self.uv[k][i][0], self.uv[k][i][1])
moved = True
if(k+1 != len(self.points[i])-1):
self.uv[i][k+1] = uv2[:]
surf = self.faces[self.surfacesID[k+1][i]].Surface
self.points[k+1][i] = surf.value(self.uv[k+1][i][0], self.uv[k+1][i][1])
if moved:
return True
return False
def createSurface(self):
""" Generates the BSpline surface.
@return False if all gone right. True otherwise.
"""
# Create a (1 x 1) plane with (nU x nV) knots
self.surf = App.Part.BSplineSurface()
nU = len(self.points)
nV = len(self.points[0])
for i in range(1,nU-1):
u = i / float(nU-1)
self.surf.insertUKnot(u,i,0.000001)
for i in range(1,nV-1):
v = i / float(nV-1)
self.surf.insertVKnot(v,i,0.000001)
# Reposition points of surface
for i in range(0,nU):
for j in range(0,nV):
u = i / float(nU-1)
v = j / float(nV-1)
point = self.points[i][j]
self.surf.movePoint(u,v,point,i+1,i+1,j+1,j+1)
# Reaconditionate surface
self.surf.exchangeUV()
deg = self.form.deg.value()
if (deg > 1) and (deg < self.surf.MaxDegree):
self.surf.increaseDegree(deg,deg)
return False
def createTask():
""" Create a task panel.
@return Task panel.
"""
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>307</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Convert surface</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="nULabel">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; color:#0000ff;&quot;&gt;Points at U&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="nU">
<property name="minimum">
<number>4</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="nVLabel">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0000;&quot;&gt;Points at V&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="nV">
<property name="minimum">
<number>4</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="degLabel">
<property name="text">
<string>Surface degree</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="deg">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>25</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,37 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
from surfUtils import Paths
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,88 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
import Draft
from FreeCAD import Vector
# Qt library
from PyQt4 import QtGui,QtCore
# Pivy
import pivy
from pivy import coin
from pivy.coin import *
# Module
from surfUtils import Paths
from surfUtils import Geometry
from surfISOCurve import Preview
class PointTracker:
def __init__(self,view,task):
self.view=view
self.task=task
task.tracker = self
self.callback = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.mouseButton)
self.callbackMove = self.view.addEventCallbackPivy(SoLocation2Event.getClassTypeId(),self.mouseMove)
def mouseMove(self, event_cb):
event = event_cb.getEvent()
surf = self.task.surf
if not surf:
return
# Get screen point
screen = event.getPosition()
ctrl = event.wasCtrlDown()
# Get snapped object if exist, else the screen point will used
point = Gui.Snapper.snap(screen, ctrl)
def mouseButton(self, event_cb):
event = event_cb.getEvent()
if event.getState() != coin.SoMouseButtonEvent.DOWN:
return
surf = self.task.surf
if not surf:
return
# Get screen point
screen = event.getPosition()
ctrl = event.wasCtrlDown()
# Get snapped object if exist, else the screen point will used
point = Gui.Snapper.snap(screen, ctrl)
if not point:
point = self.view.getPoint(screen[0],screen[1])
# Get the nearest surface point parameter
uv = surf.parameter(point)
uv = [uv[0], uv[1]]
uv[0] = uv[0] / surf.UKnotSequence[len(surf.UKnotSequence)-1]
uv[0] = max(0, min(uv[0], 1))
uv[1] = uv[1] / surf.VKnotSequence[len(surf.VKnotSequence)-1]
uv[1] = max(0, min(uv[1], 1))
# Set it into the task panel
self.task.setUV(uv[self.task.dirId])
def close(self):
# Switch off snapping
Gui.Snapper.off()
# Remove callback (Program crash otherwise)
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callback)
self.view.removeEventCallbackPivy(SoLocation2Event.getClassTypeId(),self.callbackMove)

View File

@@ -0,0 +1,125 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCADShip modules
from surfUtils import Paths
from surfUtils import Geometry
from surfUtils import Math
class Preview(object):
def __init__(self):
""" Constructor.
@param self Auto call object.
@note Start it as unactive
"""
self.obj = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
@param self Auto call object.
"""
self.clean()
self.obj = None
def update(self, surf, direction, uv):
""" Update the 3D view printing curve.
@param self Auto call object.
@param surf Surf where get the curve.
@param direction 0 if u direction, 1 if v.
@param uv Curve uv index, between 0 and 1.
@return Curve from object (as Part::Feature).
"""
# Errors
if not surf:
return None
# Get curve
if direction == 0:
curve = self.getU(surf, uv)
elif direction == 1:
curve = self.getV(surf, uv)
else:
return None
# Draw at 3D view
self.clean()
Part.show(curve.toShape())
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs)-1]
self.obj.Label = 'surfISOCurve'
return self.obj
def getU(self, surf, uv):
""" Get U curve from object.
@param self Auto call object.
@param surf Surf where get the curve.
@param uv Curve uv index, between 0 and 1.
@return Curve from object.
"""
# Errors
if not surf:
return None
if (uv < 0.0) or (uv > 1.0):
return None
# Get UV data
knots = surf.UKnotSequence
id0 = knots[0]
id1 = knots[len(knots)-1]
# Get curve
curve = surf.uIso(id0 + uv*(id1-id0))
return curve
def getV(self, surf, uv):
""" Get U curve from object.
@param self Auto call object.
@param surf Surf where get the curve.
@param uv Curve uv index, between 0 and 1.
@return Curve from object.
"""
# Errors
if not surf:
return None
if (uv < 0.0) or (uv > 1.0):
return None
# Get UV data
knots = surf.VKnotSequence
id0 = knots[0]
id1 = knots[len(knots)-1]
# Get curve
curve = surf.vIso(id0 + uv*(id1-id0))
return curve
def clean(self,Destroy=True):
""" Erase all sections from screen.
@param self Auto call object.
@param Destroy True if the object must be destroyed, False otherwise.
"""
if not self.obj:
return
FreeCADGui.ActiveDocument.hide(self.obj.Name)
if Destroy:
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj=None

View File

@@ -0,0 +1,168 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
from surfUtils import Paths, Geometry, Math, Translator
import Preview
import PointTracker
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/surfISOCurve/TaskPanel.ui"
self.preview = Preview.Preview()
self.tracker = None
def accept(self):
if not self.obj:
return True
self.obj.Label = 'ISOCurve'
self.close()
return True
def reject(self):
self.preview.clean()
self.close()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.direction = form.findChild(QtGui.QComboBox, "direction")
form.uv = form.findChild(QtGui.QSlider, "uv")
form.uvText = form.findChild(QtGui.QDoubleSpinBox, "uvText")
self.form = form
# Initial values
if self.initValues():
return True
self.obj = self.preview.update(self.surf, self.dirId, self.uv)
self.retranslateUi()
# Connect Signals and Slots
QtCore.QObject.connect(form.direction, QtCore.SIGNAL("activated(QString)"), self.selectDirection)
QtCore.QObject.connect(form.uv, QtCore.SIGNAL("valueChanged(int)"), self.onUVSlider)
QtCore.QObject.connect(form.uvText, QtCore.SIGNAL("valueChanged(double)"), self.onUVText)
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def selectDirection(self):
self.dirId = self.form.direction.currentIndex()
self.obj = self.preview.update(self.surf, self.dirId, self.uv)
if not self.obj:
msg = Translator.translate("Can't get the curve from selected object")
App.Console.PrintWarning(msg)
def onUVSlider(self, value):
uv = self.form.uv.value()
uv = uv/(float(self.form.uv.maximum()))
self.setUV(uv)
def onUVText(self, value):
uv = self.form.uvText.value()
self.setUV(uv)
def setUV(self, uv):
self.form.uv.setValue(uv*self.form.uv.maximum())
self.form.uvText.setValue(uv)
self.uv = uv
if not self.surf:
return
self.obj = self.preview.update(self.surf, self.dirId, self.uv)
if not self.obj:
msg = Translator.translate("Can't get the curve from selected object")
App.Console.PrintWarning(msg)
def initValues(self):
self.obj = None
self.dirId = 0
self.uv = 0
self.surf = None
self.selObj = Geometry.getSelectedObj()
if not self.selObj:
msg = Translator.translate("1 surface must be selected (Any object has been selected)")
App.Console.PrintError(msg)
return True
self.surf = Geometry.getSelectedSurface()
if not self.surf:
msg = Translator.translate("1 surface must be selected (Any face object found into selected objects)")
App.Console.PrintError(msg)
return True
msg = Translator.translate("Ready to work")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Get surface ISO curve"))
self.form.direction.setItemText(0, Translator.translate("U direction"))
self.form.direction.setItemText(1, Translator.translate("V direction"))
def close(self):
""" Destroy all dependant objects
@param self Main object.
"""
if self.tracker:
self.tracker.close()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
tracker = PointTracker.PointTracker(Gui.ActiveDocument.ActiveView, panel)
return panel

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>307</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Get ISO curve from surface</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QComboBox" name="direction">
<item>
<property name="text">
<string>U direction</string>
</property>
</item>
<item>
<property name="text">
<string>V direction</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSlider" name="uv">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QDoubleSpinBox" name="uvText">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,37 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
from surfUtils import Paths
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,71 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
import Draft
from FreeCAD import Vector
# Qt library
from PyQt4 import QtGui,QtCore
# Pivy
import pivy
from pivy import coin
from pivy.coin import *
# Module
from surfUtils import Paths
from surfUtils import Geometry
from surfSlice import Preview
class PointTracker:
def __init__(self,view,task):
self.view=view
self.task=task
task.tracker = self
self.callback = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.mouseButton)
self.callbackMove = self.view.addEventCallbackPivy(SoLocation2Event.getClassTypeId(),self.mouseMove)
def mouseMove(self, event_cb):
event = event_cb.getEvent()
# Get screen point
screen = event.getPosition()
ctrl = event.wasCtrlDown()
# Get snapped object if exist, else the screen point will used
point = Gui.Snapper.snap(screen, ctrl)
def mouseButton(self, event_cb):
event = event_cb.getEvent()
if event.getState() != coin.SoMouseButtonEvent.DOWN:
return
# Get screen point
screen = event.getPosition()
ctrl = event.wasCtrlDown()
# Get snapped object if exist, else the screen point will used
point = Gui.Snapper.snap(screen, ctrl)
if not point:
point = self.view.getPoint(screen[0],screen[1])
# Set it into the task panel
self.task.setR3(point)
def close(self):
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callback)

View File

@@ -0,0 +1,100 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCADShip modules
from surfUtils import Paths
from surfUtils import Geometry
from surfUtils import Math
class Preview(object):
def __init__(self):
""" Constructor.
@param self Auto call object.
@note Start it as unactive
"""
self.objs = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
@param self Auto call object.
"""
self.clean()
self.objs = None
def update(self, surf, direction, r):
""" Update the 3D view printing curve.
@param surf Surf where get the curve.
@param direction Slice plane normal vector.
@param r Absolute position at Slice plane normal direction.
@return Curve from object (as Part::Feature).
"""
# Errors
if not surf:
return None
# Get curve
curve = self.getSlice(surf, direction, r)
# Draw at 3D view
self.clean()
self.objs = []
for i in range(0,len(curve)):
for j in range(0,len(curve[i])):
Part.show(curve[i][j])
objs = FreeCAD.ActiveDocument.Objects
objs[len(objs)-1].Label = 'surfSliceCurve'
self.objs.append(objs[len(objs)-1])
return self.objs
def getSlice(self, surf, direction, r):
""" Get surface slice.
@param surf Surf where get the curve.
@param direction Slice plane normal vector.
@param r Absolute position at Slice plane normal direction.
@return Curve from object.
"""
# Errors
if not surf:
return None
# Get curve
curve = []
for i in range(0,len(surf)):
curve.append(surf[i].slice(direction, r))
return curve
def clean(self,Destroy=True):
""" Erase all sections from screen.
@param self Auto call object.
@param Destroy True if the object must be destroyed, False otherwise.
"""
if not self.objs:
return
for i in range(0,len(self.objs)):
FreeCADGui.ActiveDocument.hide(self.objs[i].Name)
if Destroy:
FreeCAD.ActiveDocument.removeObject(self.objs[i].Name)
if Destroy:
self.objs=None

View File

@@ -0,0 +1,217 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
from FreeCAD import Vector
# Qt library
from PyQt4 import QtGui,QtCore
# Module
from surfUtils import Paths, Geometry, Math, Translator
import Preview
import PointTracker
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/surfSlice/TaskPanel.ui"
self.preview = Preview.Preview()
self.tracker = None
self.dir = Vector(0.0,0.0,1.0)
def accept(self):
if not self.objs:
return True
for i in range(0,len(self.objs)):
self.objs[i].Label = 'SliceCurve'
self.close()
return True
def reject(self):
self.preview.clean()
self.close()
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.direction = form.findChild(QtGui.QComboBox, "direction")
form.r = form.findChild(QtGui.QSlider, "r")
form.rText = form.findChild(QtGui.QDoubleSpinBox, "rText")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.form.rText.setMinimum(self.bound[4])
self.form.rText.setMaximum(self.bound[5])
self.setR(self.r)
# Connect Signals and Slots
QtCore.QObject.connect(form.direction, QtCore.SIGNAL("activated(QString)"), self.selectDirection)
QtCore.QObject.connect(form.r, QtCore.SIGNAL("valueChanged(int)"), self.onRSlider)
QtCore.QObject.connect(form.rText, QtCore.SIGNAL("valueChanged(double)"), self.onRText)
return False
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (i.e. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def selectDirection(self):
if(self.form.direction.currentIndex() == 0): # XY
self.dir = Vector(0.0,0.0,1.0)
self.r = max(self.r, self.bound[4])
self.r = min(self.r, self.bound[5])
self.form.rText.setMinimum(self.bound[4])
self.form.rText.setMaximum(self.bound[5])
if(self.form.direction.currentIndex() == 1): # XZ
self.dir = Vector(0.0,1.0,0.0)
self.r = max(self.r, self.bound[2])
self.r = min(self.r, self.bound[3])
self.form.rText.setMinimum(self.bound[2])
self.form.rText.setMaximum(self.bound[3])
if(self.form.direction.currentIndex() == 2): # YZ
self.dir = Vector(1.0,0.0,0.0)
self.r = max(self.r, self.bound[0])
self.r = min(self.r, self.bound[1])
self.form.rText.setMinimum(self.bound[0])
self.form.rText.setMaximum(self.bound[1])
self.objs = self.preview.update(self.face, self.dir, self.r)
if not self.objs:
msg = Translator.translate("Can't calculate section")
App.Console.PrintWarning(msg)
def onRSlider(self, value):
# Get r at [0,1] interval
r = self.form.r.value()
r = r/(float(self.form.r.maximum()))
# Expand to real interval
dr = self.form.rText.maximum()-self.form.rText.minimum()
r = r*dr + self.form.rText.minimum()
# Set value
self.setR(r)
def onRText(self, value):
r = self.form.rText.value()
self.setR(r)
def setR(self, r):
self.form.rText.setValue(r)
self.r = max(self.form.rText.minimum(), min(self.form.rText.maximum(), r))
dr = self.form.rText.maximum()-self.form.rText.minimum()
r = (r - self.form.rText.minimum())/dr*self.form.r.maximum()
self.form.r.setValue(r)
if not self.face:
return
self.objs = self.preview.update(self.face, self.dir, self.r)
if not self.objs:
msg = Translator.translate("Can't calculate section")
App.Console.PrintWarning(msg)
def setR3(self, r):
if(self.form.direction.currentIndex() == 0): # XY
self.setR(r.z)
if(self.form.direction.currentIndex() == 1): # XZ
self.setR(r.y)
if(self.form.direction.currentIndex() == 2): # YZ
self.setR(r.x)
def initValues(self):
self.objs = None
self.dir = Vector(0.0,0.0,1.0)
self.r = 0.0
self.face = None
self.selObj = Geometry.getSelectedObj()
if not self.selObj:
msg = Translator.translate("At least 1 surface must be selected (Any selected object)")
App.Console.PrintError(msg)
return True
self.face = Geometry.getFaces()
if not self.face:
msg = Translator.translate("At least 1 surface must be selected (Any face object found into selected objects)")
App.Console.PrintError(msg)
return True
bound = self.face[0].BoundBox
self.bound = [bound.XMin, bound.XMax, bound.YMin, bound.YMax, bound.ZMin, bound.ZMax]
for i in range(1,len(self.face)):
face = self.face[i]
bound = face.BoundBox
self.bound[0] = min(self.bound[0],bound.XMin)
self.bound[1] = min(self.bound[1],bound.XMax)
self.bound[2] = min(self.bound[2],bound.YMin)
self.bound[3] = min(self.bound[3],bound.YMax)
self.bound[4] = min(self.bound[4],bound.ZMin)
self.bound[5] = min(self.bound[5],bound.ZMax)
self.r = max(self.r, self.bound[4])
self.r = min(self.r, self.bound[5])
msg = Translator.translate("Ready to work")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Get surface slice"))
def close(self):
""" Destroy all dependant objects
@param self Main object.
"""
if self.tracker:
self.tracker.close()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
tracker = PointTracker.PointTracker(Gui.ActiveDocument.ActiveView, panel)
return panel

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>307</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Get surface slice</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QComboBox" name="direction">
<item>
<property name="text">
<string>XY</string>
</property>
</item>
<item>
<property name="text">
<string>XZ</string>
</property>
</item>
<item>
<property name="text">
<string>YZ</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSlider" name="r">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QDoubleSpinBox" name="rText">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,37 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
from surfUtils import Paths
def load():
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -0,0 +1,174 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD
import FreeCAD, FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
# FreeCAD ship
from surfUtils import Math
def getSelectedObjs():
""" Returns the selected objects list
@return Selected objects list
"""
return FreeCADGui.Selection.getSelection()
def getSelectedObj():
""" Returns the first element of the selected objects list
@return Selected object. None if errors happens
"""
objs = FreeCADGui.Selection.getSelection()
if not objs:
return None
if not len(objs):
return None
obj = objs[0]
return FreeCAD.ActiveDocument.getObject(obj.Name)
def getEdges(objs=None):
""" Returns object edges (list of them)
@param objs Object to get the faces, none if selected
object may used.
@return Selected edges. None if errors happens
"""
edges = []
if not objs:
objs = FreeCADGui.Selection.getSelection()
if not objs:
return None
for i in range(0, len(objs)):
obj = objs[i]
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
objEdges = obj.Edges
if not objEdges:
continue
for j in range(0, len(objEdges)):
edges.append(objEdges[j])
return edges
def getFaces(obj=None):
""" Returns object faces (list of them)
@param obj Object to get the faces, none if selected
object may used.
@return Selected faces. None if errors happens
"""
if not obj:
obj = getSelectedObj()
if not obj:
return None
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
# get face
faces = obj.Faces
if not faces:
return None
if not len(faces):
return None
return faces
def getSelectedSurface(obj=None):
""" Returns object surface (the first of the list)
@param obj Object to get the surface, none if selected
object may used.
@return Selected surface. None if errors happens
"""
faces = getFaces(obj)
if not faces:
return None
obj = faces[0]
# get surface
surf = obj.Surface
if not surf:
return None
return surf
def getBorders(objs=None):
""" Returns the borders of all selected objects as edge array
@param objs Objects to get the edges, none if selected objects
may used.
@return Borders
"""
edges = []
if not objs:
objs = FreeCADGui.Selection.getSelection()
if not objs:
return None
if len(objs) < 1:
return None
for i in range(0, len(objs)):
faces = getFaces(objs[i])
if not faces:
continue
for j in range(0, len(faces)):
edgList = faces[j].Edges
for k in range(0, len(edgList)):
edges.append(edgList[k])
return edges
def lineFaceSection(line,surface):
""" Returns the point of section of a line with a face
@param line Line object, that can be a curve.
@param surface Surface object (must be a Part::Shape)
@return Section points array, [] if line don't cut surface
"""
# Get initial data
result = []
vertexes = line.Vertexes
nVertex = len(vertexes)
# Perform the cut
section = line.cut(surface)
# Filter all old points
points = section.Vertexes
nPoint = len(points)
if nPoint <= nVertex:
# Any valid point
result
for i in range(0,nPoint):
disp = len(result)
flag = 0
if not Math.isAprox(points[i].X,vertexes[i-disp].X,0.0001):
flag = flag+1
if not Math.isAprox(points[i].Y,vertexes[i-disp].Y,0.0001):
flag = flag+1
if not Math.isAprox(points[i].Z,vertexes[i-disp].Z,0.0001):
flag = flag+1
if flag > 0:
result.append(points[i])
return result

View File

@@ -0,0 +1,57 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
def isAprox(a,b,tol=0.0001):
"""returns if a value is into (b-tol,b+tol)
@param a Value to compare.
@param b Center of valid interval
@param tol Radius of valid interval
@return True if a is into (b-tol,b+tol), False otherwise
"""
if (a < b+abs(tol)) and (a > b-abs(tol)):
return True
return False
def isSamePoint(a,b,tol=0.0001):
"""returns if two points are the same with a provided tolerance
@param a Point to compare.
@param b Reference point.
@param tol Radius of valid interval
@return True if twice point are the same, False otherwise
@note FreeCAD::Base::Vector types must be provided
"""
if isAprox(a.x,b.x,tol) and isAprox(a.y,b.y,tol) and isAprox(a.z,b.z,tol):
return True
return False
def isSameVertex(a,b,tol=0.0001):
"""returns if two points are the same with a provided tolerance
@param a Point to compare.
@param b Reference point.
@param tol Radius of valid interval
@return True if twice point are the same, False otherwise
@note FreeCAD::Part::Vertex types must be provided
"""
if isAprox(a.X,b.X,tol) and isAprox(a.Y,b.Y,tol) and isAprox(a.Z,b.Z,tol):
return True
return False

Some files were not shown because too many files have changed in this diff Show More