Merge branch 'master' of ssh://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad

This commit is contained in:
jriegel 2012-08-04 11:53:32 +02:00
commit 5aff6be27e
65 changed files with 11068 additions and 173 deletions

View File

@ -1516,10 +1516,10 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::map<DocumentObje
// remove number from end to avoid lengthy names
std::string objname = obj->getNameInDocument();
if (!keepdigitsatend) {
size_t lastpos = objname.length()-1;
while (objname[lastpos] >= 48 && objname[lastpos] <= 57)
lastpos--;
objname = objname.substr(0, lastpos+1);
size_t lastpos = objname.length()-1;
while (objname[lastpos] >= 48 && objname[lastpos] <= 57)
lastpos--;
objname = objname.substr(0, lastpos+1);
}
DocumentObject* copy = addObject(obj->getTypeId().getName(),objname.c_str());
if (!copy) return 0;

View File

@ -346,10 +346,10 @@ void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
Property *PropertyFileIncluded::Copy(void) const
{
PropertyFileIncluded *p= new PropertyFileIncluded();
PropertyFileIncluded *prop = new PropertyFileIncluded();
// remember the base name
p->_BaseFileName = _BaseFileName;
prop->_BaseFileName = _BaseFileName;
if (!_cValue.empty()) {
Base::FileInfo file(_cValue);
@ -361,11 +361,11 @@ Property *PropertyFileIncluded::Copy(void) const
bool done = file.renameFile(NewName.filePath().c_str());
assert(done);
// remember the new name for the Undo
Base::Console().Log("Copy this=%p Before=%s After=%s\n",p,p->_cValue.c_str(),NewName.filePath().c_str());
p->_cValue = NewName.filePath().c_str();
Base::Console().Log("Copy this=%p Before=%s After=%s\n",prop,prop->_cValue.c_str(),NewName.filePath().c_str());
prop->_cValue = NewName.filePath().c_str();
}
return p;
return prop;
}
void PropertyFileIncluded::Paste(const Property &from)
@ -376,6 +376,9 @@ void PropertyFileIncluded::Paste(const Property &from)
file.deleteFile();
const PropertyFileIncluded &fileInc = dynamic_cast<const PropertyFileIncluded&>(from);
// set the base name
_BaseFileName = fileInc._BaseFileName;
if (!fileInc._cValue.empty()) {
// move the saved files back in place
Base::FileInfo NewFile(fileInc._cValue);

View File

@ -894,9 +894,9 @@ bool StdCmdPaste::isActive(void)
return getMainWindow()->canInsertFromMimeData(mime);
}
DEF_STD_CMD_A(StdCmdDDuplicateSelection);
DEF_STD_CMD_A(StdCmdDuplicateSelection);
StdCmdDDuplicateSelection::StdCmdDDuplicateSelection()
StdCmdDuplicateSelection::StdCmdDuplicateSelection()
:Command("Std_DuplicateSelection")
{
sAppModule = "Edit";
@ -907,7 +907,7 @@ StdCmdDDuplicateSelection::StdCmdDDuplicateSelection()
sStatusTip = QT_TR_NOOP("Put duplicates of the selected objects to the active document");
}
void StdCmdDDuplicateSelection::activated(int iMsg)
void StdCmdDuplicateSelection::activated(int iMsg)
{
App::Document* act = App::GetApplication().getActiveDocument();
if (!act)
@ -964,7 +964,7 @@ void StdCmdDDuplicateSelection::activated(int iMsg)
}
}
bool StdCmdDDuplicateSelection::isActive(void)
bool StdCmdDuplicateSelection::isActive(void)
{
return Gui::Selection().hasSelection();
}
@ -1275,7 +1275,7 @@ void CreateDocCommands(void)
rcCmdMgr.addCommand(new StdCmdCut());
rcCmdMgr.addCommand(new StdCmdCopy());
rcCmdMgr.addCommand(new StdCmdPaste());
rcCmdMgr.addCommand(new StdCmdDDuplicateSelection());
rcCmdMgr.addCommand(new StdCmdDuplicateSelection());
rcCmdMgr.addCommand(new StdCmdSelectAll());
rcCmdMgr.addCommand(new StdCmdDelete());
rcCmdMgr.addCommand(new StdCmdRefresh());

View File

@ -25,6 +25,7 @@
#ifndef _PreComp_
# include <cstring>
# include <algorithm>
# include <QDebug>
# include <QMessageBox>
#endif
@ -89,6 +90,15 @@ void DlgPreferencesImp::setupPages()
}
fileName = std::string("preferences-") + fileName;
QPixmap icon = Gui::BitmapFactory().pixmapFromSvg(fileName.c_str(), QSize(96,96));
if (icon.isNull()) {
icon = Gui::BitmapFactory().pixmap(fileName.c_str());
if (icon.isNull()) {
qWarning() << "No group icon found for " << fileName.c_str();
}
else if (icon.size() != QSize(96,96)) {
qWarning() << "Group icon for " << fileName.c_str() << " is not of size 96x96";
}
}
item->setIcon(icon);
item->setTextAlignment(Qt::AlignHCenter);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

View File

@ -99,10 +99,15 @@ Placement::Placement(QWidget* parent, Qt::WFlags fl)
connect(signalMapper, SIGNAL(mapped(int)),
this, SLOT(onPlacementChanged(int)));
connectAct = Application::Instance->signalActiveDocument.connect
(boost::bind(&Placement::slotActiveDocument, this, _1));
App::Document* activeDoc = App::GetApplication().getActiveDocument();
if (activeDoc) documents.insert(activeDoc->getName());
}
Placement::~Placement()
{
connectAct.disconnect();
delete ui;
}
@ -113,6 +118,36 @@ void Placement::showDefaultButtons(bool ok)
ui->applyButton->setVisible(ok);
}
void Placement::slotActiveDocument(const Gui::Document& doc)
{
documents.insert(doc.getDocument()->getName());
}
void Placement::revertTransformation()
{
for (std::set<std::string>::iterator it = documents.begin(); it != documents.end(); ++it) {
Gui::Document* document = Application::Instance->getDocument(it->c_str());
if (!document) continue;
std::vector<App::DocumentObject*> obj = document->getDocument()->
getObjectsOfType(App::DocumentObject::getClassTypeId());
if (!obj.empty()) {
for (std::vector<App::DocumentObject*>::iterator it=obj.begin();it!=obj.end();++it) {
std::map<std::string,App::Property*> props;
(*it)->getPropertyMap(props);
// search for the placement property
std::map<std::string,App::Property*>::iterator jt;
jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName));
if (jt != props.end()) {
Base::Placement cur = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
Gui::ViewProvider* vp = document->getViewProvider(*it);
if (vp) vp->setTransformation(cur.toMatrix());
}
}
}
}
}
void Placement::applyPlacement(const Base::Placement& p, bool incremental, bool data)
{
Gui::Document* document = Application::Instance->activeDocument();
@ -225,12 +260,15 @@ void Placement::reject()
QVariant data = QVariant::fromValue<Base::Placement>(plm);
/*emit*/ placementChanged(data, true, false);
revertTransformation();
QDialog::reject();
}
void Placement::accept()
{
on_applyButton_clicked();
revertTransformation();
QDialog::accept();
}

View File

@ -28,9 +28,14 @@
#include <Gui/TaskView/TaskView.h>
#include <Base/Placement.h>
#include <boost/signals.hpp>
#include <boost/bind.hpp>
class QSignalMapper;
namespace Gui {
class Document;
namespace Dialog {
class Ui_Placement;
@ -64,6 +69,8 @@ private:
Base::Placement getPlacementData() const;
void directionActivated(int);
void applyPlacement(const Base::Placement& p, bool incremental, bool data);
void revertTransformation();
void slotActiveDocument(const Gui::Document&);
Q_SIGNALS:
void placementChanged(const QVariant &, bool, bool);
@ -71,10 +78,13 @@ Q_SIGNALS:
private:
typedef Gui::LocationInterfaceComp<Ui_Placement> Ui_PlacementComp;
typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection;
Ui_PlacementComp* ui;
QSignalMapper* signalMapper;
Connection connectAct;
Base::Placement ref;
std::string propertyName; // the name of the placement property
std::set<std::string> documents;
friend class TaskPlacement;
};

View File

@ -701,10 +701,14 @@ void PythonConsole::runSource(const QString& line)
catch (const Base::SystemExitException&) {
ParameterGrp::handle hPrefGrp = getWindowParameter();
bool check = hPrefGrp->GetBool("CheckSystemExit",true);
if (!check) qApp->quit();
int ret = QMessageBox::question(this, tr("System exit"), tr("The application is still running.\nDo you want to exit without saving your data?"),
QMessageBox::Yes, QMessageBox::No|QMessageBox::Escape|QMessageBox::Default);
int ret = QMessageBox::Yes;
if (check) {
ret = QMessageBox::question(this, tr("System exit"),
tr("The application is still running.\nDo you want to exit without saving your data?"),
QMessageBox::Yes, QMessageBox::No|QMessageBox::Escape|QMessageBox::Default);
}
if (ret == QMessageBox::Yes) {
PyErr_Clear();
qApp->quit();
}
else {

View File

@ -235,6 +235,79 @@ def makeFace(wires,method=2,cleanup=False):
#print "makeFace: final face:",mf.Faces
return mf.Faces[0]
def closeHole(shape):
'''closeHole(shape): closes a hole in an open shape'''
import DraftGeomUtils, Part
# creating an edges lookup table
lut = {}
for face in shape.Faces:
for edge in face.Edges:
hc = edge.hashCode()
if lut.has_key(hc):
lut[hc] = lut[hc] + 1
else:
lut[hc] = 1
# filter out the edges shared by more than one face
bound = []
for e in shape.Edges:
if lut[e.hashCode()] == 1:
bound.append(e)
bound = DraftGeomUtils.sortEdges(bound)
try:
nface = Part.Face(Part.Wire(bound))
shell = Part.makeShell(shape.Faces+[nface])
solid = Part.Solid(shell)
except:
raise
else:
return solid
def getCutVolume(cutplane,shapes):
"""getCutVolume(cutplane,shapes): returns a cut face and a cut volume
from the given shapes and the given cutting plane"""
import Part
placement = FreeCAD.Placement(cutplane.Placement)
# building boundbox
bb = shapes[0].BoundBox
for sh in shapes[1:]:
bb.add(sh.BoundBox)
bb.enlarge(1)
um = vm = wm = 0
ax = placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
u = placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
if not bb.isCutPlane(placement.Base,ax):
print "No objects are cut by the plane"
return None,None
else:
corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin),
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin),
FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax),
FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax),
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
for c in corners:
dv = c.sub(placement.Base)
um1 = DraftVecUtils.project(dv,u).Length
um = max(um,um1)
vm1 = DraftVecUtils.project(dv,v).Length
vm = max(vm,vm1)
wm1 = DraftVecUtils.project(dv,ax).Length
wm = max(wm,wm1)
p1 = FreeCAD.Vector(-um,vm,0)
p2 = FreeCAD.Vector(um,vm,0)
p3 = FreeCAD.Vector(um,-vm,0)
p4 = FreeCAD.Vector(-um,-vm,0)
cutface = Part.makePolygon([p1,p2,p3,p4,p1])
cutface = Part.Face(cutface)
cutface.Placement = placement
cutnormal = DraftVecUtils.scaleTo(ax,wm)
cutvolume = cutface.extrude(cutnormal)
return cutface,cutvolume
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'''
@ -242,10 +315,10 @@ def meshToShape(obj,mark=True):
name = obj.Name
import Part, MeshPart, DraftGeomUtils
if "Mesh" in obj.PropertiesList:
faces = []
faces = []
mesh = obj.Mesh
plac = obj.Placement
segments = mesh.getPlanes(0.001) # use rather strict tolerance here
segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here
print len(segments)," segments ",segments
for i in segments:
print "treating",segments.index(i),i
@ -262,7 +335,7 @@ def meshToShape(obj,mark=True):
se = Part.makeShell(faces)
solid = Part.Solid(se)
except:
pass
raise
else:
if solid.isClosed():
FreeCAD.ActiveDocument.removeObject(name)
@ -354,6 +427,34 @@ def download(url):
return None
else:
return filepath
def check(objectslist,includehidden=True):
"""check(objectslist,includehidden=True): checks if the given objects contain only solids"""
objs = Draft.getGroupContents(objectslist)
if not includehidden:
objs = Draft.removeHidden(objs)
bad = []
for o in objs:
if not o.isDerivedFrom("Part::Feature"):
bad.append([o,"is not a Part-based object"])
else:
s = o.Shape
if not s.isClosed():
bad.append([o,"is not closed"])
elif not s.isValid():
bad.append([o,"is not valid"])
elif not s.Solids:
bad.append([o,"doesn't contain any solid"])
else:
f = 0
for sol in s.Solids:
f += len(sol.Faces)
if not sol.isClosed():
bad.append([o,"contains a non-closed solid"])
if len(s.Faces) != f:
bad.append([o,"contains faces that are not part of any solid"])
return bad
# command definitions ###############################################
@ -484,7 +585,8 @@ class _CommandMeshToShape:
class _CommandSelectNonSolidMeshes:
"the Arch SelectNonSolidMeshes command definition"
def GetResources(self):
return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SelectNonSolidMeshes","Select non-manifold meshes"),
return {'Pixmap': 'Arch_SelectNonManifold.svg',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SelectNonSolidMeshes","Select non-manifold meshes"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SelectNonSolidMeshes","Selects all non-manifold meshes from the document or from the selected groups")}
def Activated(self):
@ -522,9 +624,54 @@ class _CommandRemoveShape:
sel = FreeCADGui.Selection.getSelection()
removeShape(sel)
class _CommandCloseHoles:
"the Arch CloseHoles command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_CloseHoles',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_CloseHoles","Close holes"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_CloseHoles","Closes holes in open shapes, turning them solids")}
def IsActive(self):
if FreeCADGui.Selection.getSelection():
return True
else:
return False
def Activated(self):
for o in FreeCADGui.Selection.getSelection():
s = closeHole(o.Shape)
if s:
o.Shape = s
class _CommandCheck:
"the Arch Check command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Check',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Check","Check"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Check","Checks the selected objects for problems")}
def IsActive(self):
if FreeCADGui.Selection.getSelection():
return True
else:
return False
def Activated(self):
result = check(FreeCADGui.Selection.getSelection())
if not result:
FreeCAD.Console.PrintMessage("All good! no problems found")
else:
FreeCADGui.Selection.clearSelection()
for i in result:
FreeCAD.Console.PrintWarning("Object "+i[0].Name+" ("+i[0].Label+") "+i[1])
FreeCADGui.Selection.addSelection(i[0])
FreeCADGui.addCommand('Arch_Add',_CommandAdd())
FreeCADGui.addCommand('Arch_Remove',_CommandRemove())
FreeCADGui.addCommand('Arch_SplitMesh',_CommandSplitMesh())
FreeCADGui.addCommand('Arch_MeshToShape',_CommandMeshToShape())
FreeCADGui.addCommand('Arch_SelectNonSolidMeshes',_CommandSelectNonSolidMeshes())
FreeCADGui.addCommand('Arch_RemoveShape',_CommandRemoveShape())
FreeCADGui.addCommand('Arch_CloseHoles',_CommandCloseHoles())
FreeCADGui.addCommand('Arch_Check',_CommandCheck())

View File

@ -186,7 +186,7 @@ class _ArchDrawingView:
obj.addProperty("App::PropertyEnumeration","RenderingMode","Drawing View","The rendering mode to use")
obj.addProperty("App::PropertyFloat","LineWidth","Drawing View","The line width of the rendered objects")
obj.RenderingMode = ["Solid","Wireframe"]
obj.RenderingMode = "Solid"
obj.RenderingMode = "Wireframe"
obj.LineWidth = 0.35
obj.Proxy = self
self.Type = "DrawingView"
@ -206,6 +206,7 @@ class _ArchDrawingView:
if obj.Source:
if obj.Source.Objects:
objs = Draft.getGroupContents(obj.Source.Objects)
objs = Draft.removeHidden(objs)
svg = ''
# generating SVG
@ -223,18 +224,33 @@ class _ArchDrawingView:
else:
# render using the Drawing module
import Drawing
import Drawing, Part
shapes = []
p = FreeCAD.Placement(obj.Source.Placement)
direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
for o in objs:
if o.isDerivedFrom("Part::Feature"):
shapes.append(o.Shape)
if shapes:
base = shape.pop()
for sh in shapes:
base = base.fuse(sh)
svgf = Drawing.projectToSVG(base,DraftVecUtils.neg(direction))
shapes.extend(o.Shape.Solids)
cutface,cutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
if cutvolume:
nsh = []
for sh in shapes:
for sol in sh.Solids:
c = sol.cut(cutvolume)
nsh.append(c)
shapes = nsh
base = Part.makeCompound(shapes)
#if shapes:
# base = shapes.pop().copy()
#for sh in shapes:
# try:
# base = base.fuse(sh)
# except:
# print "unable to fuse, passing..."
svgf = Drawing.projectToSVG(base,direction)
if svgf:
svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"')
svgf = svgf.replace('stroke-width="1"','stroke-width="' + str(linewidth) + 'px"')
svgf = svgf.replace('stroke-width:0.01','stroke-width:' + str(linewidth) + 'px')
svg += svgf

View File

@ -228,42 +228,11 @@ class Renderer:
if DEBUG: print "No objects to make sections"
else:
fill = (1.0,1.0,1.0,1.0)
placement = FreeCAD.Placement(cutplane.Placement)
# building boundbox
bb = self.shapes[0][0].BoundBox
for sh in self.shapes[1:]:
bb.add(sh[0].BoundBox)
bb.enlarge(1)
um = vm = wm = 0
if not bb.isCutPlane(placement.Base,self.wp.axis):
if DEBUG: print "No objects are cut by the plane"
else:
corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin),
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin),
FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax),
FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax),
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
for c in corners:
dv = c.sub(placement.Base)
um1 = DraftVecUtils.project(dv,self.wp.u).Length
um = max(um,um1)
vm1 = DraftVecUtils.project(dv,self.wp.v).Length
vm = max(vm,vm1)
wm1 = DraftVecUtils.project(dv,self.wp.axis).Length
wm = max(wm,wm1)
p1 = FreeCAD.Vector(-um,vm,0)
p2 = FreeCAD.Vector(um,vm,0)
p3 = FreeCAD.Vector(um,-vm,0)
p4 = FreeCAD.Vector(-um,-vm,0)
cutface = Part.makePolygon([p1,p2,p3,p4,p1])
cutface = Part.Face(cutface)
cutface.Placement = placement
cutnormal = DraftVecUtils.scaleTo(self.wp.axis,wm)
cutvolume = cutface.extrude(cutnormal)
shps = []
for sh in self.shapes:
shps.append(sh[0])
cutface,cutvolume = ArchCommands.getCutVolume(cutplane,shps)
if cutface and cutvolume:
shapes = []
faces = []
sections = []

View File

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

View File

@ -65,7 +65,9 @@ class ArchWorkbench(Workbench):
"Arch_Window","Arch_Roof","Arch_Axis",
"Arch_SectionPlane","Arch_Add","Arch_Remove"]
self.meshtools = ["Arch_SplitMesh","Arch_MeshToShape",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape"]
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles"]
self.calctools = ["Arch_Check"]
# draft tools
self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc",
@ -85,6 +87,7 @@ class ArchWorkbench(Workbench):
self.appendToolbar(str(DraftTools.translate("arch","Draft tools")),self.drafttools)
self.appendToolbar(str(DraftTools.translate("arch","Draft mod tools")),self.draftmodtools)
self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Conversion Tools"))],self.meshtools)
self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Calculation Tools"))],self.calctools)
self.appendMenu(str(DraftTools.translate("arch","&Architecture")),self.archtools)
self.appendMenu(str(DraftTools.translate("arch","&Draft")),self.drafttools+self.draftmodtools)
self.appendMenu([str(DraftTools.translate("arch","&Draft")),str(DraftTools.translate("arch","Context Tools"))],self.draftcontexttools)

View File

@ -62,6 +62,9 @@ EXTRA_DIST = \
Resources/icons/Arch_Axis.svg \
Resources/icons/Arch_Axis_Tree.svg \
Resources/icons/Arch_Roof.svg \
Resources/icons/Arch_Roof_Tree.svg
Resources/icons/Arch_Roof_Tree.svg \
Resources/icons/Arch_CloseHoles.svg \
Resources/icons/Arch_Check.svg \
Resources/icons/Arch_SelectNonManifold.svg \
Resources/ui/archprefs-base.ui

View File

@ -26,6 +26,9 @@
<file>icons/Arch_Axis_Tree.svg</file>
<file>icons/Arch_Roof.svg</file>
<file>icons/Arch_Roof_Tree.svg</file>
<file>icons/Arch_CloseHoles.svg</file>
<file>icons/Arch_Check.svg</file>
<file>icons/Arch_SelectNonManifold.svg</file>
<file>ui/archprefs-base.ui</file>
<file>translations/Arch_af.qm</file>
<file>translations/Arch_de.qm</file>

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2980"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Arch_CloseHoles.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2982">
<linearGradient
id="linearGradient3886">
<stop
style="stop-color:#069c04;stop-opacity:1;"
offset="0"
id="stop3888" />
<stop
style="stop-color:#30ff00;stop-opacity:1;"
offset="1"
id="stop3890" />
</linearGradient>
<linearGradient
id="linearGradient3864">
<stop
id="stop3866"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2988" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3076"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.58019421,1.0078171,-1.9050269,1.0967121,56.377421,-198.90838)"
cx="51.328892"
cy="31.074146"
fx="51.328892"
fy="31.074146"
r="19.571428" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3886"
id="linearGradient3892"
x1="24.545456"
y1="46.18182"
x2="59.818184"
y2="46.18182"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3886-6">
<stop
style="stop-color:#069c04;stop-opacity:1;"
offset="0"
id="stop3888-3" />
<stop
style="stop-color:#30ff00;stop-opacity:1;"
offset="1"
id="stop3890-8" />
</linearGradient>
<linearGradient
y2="46.18182"
x2="59.818184"
y1="46.18182"
x1="24.545456"
gradientUnits="userSpaceOnUse"
id="linearGradient3911"
xlink:href="#linearGradient3886-6"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="17.873035"
inkscape:cy="23.707214"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="777"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2985">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path3823"
d="M 25.79697,8.8856058 6.7270788,15.79506 35.055974,19.6179 34.359592,54.387106 50.969909,43.854438 51.524141,10.761585 25.79697,8.8856058 z"
style="fill:#0034ff;fill-opacity:1;fill-rule:evenodd;stroke:#000935;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
id="path3827"
d="M 35.296022,19.106371 51.39353,11.013528"
style="fill:url(#radialGradient3076);fill-opacity:1;fill-rule:evenodd;stroke:#000935;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path3825"
d="m 5.966166,15.823942 29.554968,3.239158 0,35.106575 L 5.5667691,49.295192 5.966166,15.823942 z"
style="color:#000000;fill:#0034ff;fill-opacity:1;fill-rule:evenodd;stroke:#000935;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:type="arc"
style="color:#000000;fill:url(#linearGradient3892);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path3884"
sodipodi:cx="42.18182"
sodipodi:cy="46.18182"
sodipodi:rx="17.636364"
sodipodi:ry="17.636364"
d="m 59.818184,46.18182 a 17.636364,17.636364 0 1 1 -35.272728,0 17.636364,17.636364 0 1 1 35.272728,0 z"
transform="matrix(0.70194052,-0.71223557,0.71223557,0.70194052,-22.865098,40.171958)" />
<path
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.2856828;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 21.165568,29.935381 c 12.00975,4.422569 16.606075,26.535415 16.606075,26.535415 0,0 3.82595,-10.925561 9.192647,-17.362678 6.444989,-7.730482 14.233778,-15.397094 14.233778,-15.397094 0,0 -11.928284,4.439851 -15.864731,8.845139 -4.204093,4.704812 -6.672083,9.500333 -6.672083,9.500333 0,0 0.741342,-2.620782 -4.892861,-8.189943 -5.634204,-5.569161 -12.602825,-3.931172 -12.602825,-3.931172 z"
id="path3894"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscscsc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2980"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Tree_Part.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2982">
<linearGradient
id="linearGradient3864">
<stop
id="stop3866"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3850"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6028459,1.0471639,-1.9794021,1.1395295,127.9588,-74.456907)"
cx="51.328892"
cy="31.074146"
fx="51.328892"
fy="31.074146"
r="19.571428" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2988" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3076"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.58019421,1.0078171,-1.9050269,1.0967121,59.286512,-197.81747)"
cx="51.328892"
cy="31.074146"
fx="51.328892"
fy="31.074146"
r="19.571428" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="17.933431"
inkscape:cy="19.33227"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="777"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2985">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path3823"
d="M 28.706061,9.9765149 9.6361697,16.885969 37.965065,20.708809 37.268683,55.478015 53.879,44.945347 54.433232,11.852494 28.706061,9.9765149 z"
style="fill:#0034ff;fill-opacity:1;fill-rule:evenodd;stroke:#000935;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
id="path3827"
d="M 38.205113,20.19728 54.302621,12.104437"
style="fill:url(#radialGradient3076);fill-opacity:1;fill-rule:evenodd;stroke:#000935;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path3825"
d="m 8.8752569,16.914851 29.5549681,3.239158 0,35.106575 L 8.47586,50.386101 8.8752569,16.914851 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#4e0404;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg3052"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Tree_Mesh.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs3054">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective3060" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.4041996"
inkscape:cx="38.197927"
inkscape:cy="30.057626"
inkscape:current-layer="g3884"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="777"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata3057">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3884"
transform="matrix(-0.2109556,0.9774957,0.8838524,0.1907462,-82.022362,-158.02055)">
<path
sodipodi:nodetypes="ccccccccccccc"
id="path3866"
d="M 184.06062,145.97669 C 181.22675,145.40157 156.20116,140.95084 156.20116,140.95084 L 144.01145,149.90279 L 145.67879,163.80547 L 159.84692,172.90767 L 148.28301,184.75924 L 134.6552,170.63364 L 164.9947,183.29864 L 174.20518,194.04864 L 184.66465,180.68444 L 169.41264,170.28145 L 170.03744,156.37876 L 184.06062,145.97669 z"
style="fill:#07ff00;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4.20656422;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path3876"
d="M 170.125,156.625 L 145,150"
style="opacity:1;fill:#07ff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.15492317;stroke-linecap:round;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" />
<path
id="path3878"
d="M 170.125,170.75 L 146.625,163.75"
style="opacity:1;fill:#07ff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.15492317;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="ccccc"
id="path3880"
d="M 165,183.25 L 135.75,171.375 L 148.75,186 L 174.625,196 L 165,183.25 z"
style="opacity:1;fill:#07ff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.15492317;stroke-linecap:round;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
id="path3882"
d="M 158.75,172.75 L 184.75,181.125"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.15492317;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -278,6 +278,15 @@ def getGroupContents(objectslist,walls=False):
newlist.append(o)
return newlist
def removeHidden(objectslist):
"""removeHidden(objectslist): removes hidden objects from the list"""
newlist = objectslist[:]
for o in objectslist:
if o.ViewObject:
if not o.ViewObject.isVisible():
newlist.remove(o)
return newlist
def printShape(shape):
"""prints detailed information of a shape"""
print "solids: ", len(shape.Solids)
@ -347,6 +356,8 @@ def formatObject(target,origin=None):
setattr(obrep,p,val)
if matchrep.DisplayMode in obrep.listDisplayModes():
obrep.DisplayMode = matchrep.DisplayMode
if hasattr(matchrep,"DiffuseColor") and hasattr(obrep,"DiffuseColor"):
obrep.DiffuseColor = matchrep.DiffuseColor
def getSelection():
"getSelection(): returns the current FreeCAD selection"
@ -1057,7 +1068,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy
for o in objectslist:
o.ViewObject.hide()
if gui:
_ViewProviderDraftPart(obj.ViewObject)
_ViewProviderClone(obj.ViewObject)
formatObject(obj,objectslist[-1])
select(obj)
return obj
@ -1649,10 +1660,10 @@ def clone(obj,delta=None):
_Clone(cl)
if gui:
_ViewProviderClone(cl.ViewObject)
formatObject(cl,obj[0])
cl.Objects = obj
if delta:
cl.Placement.move(delta)
formatObject(cl,obj[0])
return cl
def heal(objlist=None,delete=True,reparent=True):

View File

@ -11,7 +11,13 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QCoreApplication>
# include <QDir>
# include <QFile>
# include <QFileInfo>
# include <QMessageBox>
# include <QRegExp>
#endif
#include <vector>
@ -88,18 +94,16 @@ CmdDrawingNewPage::CmdDrawingNewPage()
void CmdDrawingNewPage::activated(int iMsg)
{
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QAction* a = pcAction->actions()[iMsg];
std::string FeatName = getUniqueObjectName("Page");
if (iMsg == 3) {
QFileInfo tfi(a->property("Template").toString());
if (tfi.isReadable()) {
openCommand("Drawing create page");
doCommand(Doc,"App.activeDocument().addObject('Drawing::FeaturePage','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Template = 'A3_Landscape.svg'",FeatName.c_str());
commitCommand();
}
else if (iMsg == 4) {
openCommand("Drawing create page");
doCommand(Doc,"App.activeDocument().addObject('Drawing::FeaturePage','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Template = 'A4_Landscape.svg'",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Template = '%s'",FeatName.c_str(), (const char*)tfi.filePath().toUtf8());
commitCommand();
}
else {
@ -115,25 +119,45 @@ Gui::Action * CmdDrawingNewPage::createAction(void)
pcAction->setDropDownMenu(true);
applyCommandData(pcAction);
QAction* a0 = pcAction->addAction(QString());
a0->setIcon(Gui::BitmapFactory().pixmap("actions/drawing-landscape-A0"));
QAction* defaultAction = 0;
int defaultId = 0;
QAction* a1 = pcAction->addAction(QString());
a1->setIcon(Gui::BitmapFactory().pixmap("actions/drawing-landscape-A1"));
std::string path = App::Application::getResourceDir();
path += "Mod/Drawing/Templates/";
QDir dir(QString::fromUtf8(path.c_str()), QString::fromAscii("A*_Landscape.svg"));
for (unsigned int i=0; i<dir.count(); i++ ) {
QRegExp rx(QString::fromAscii("A(\\d)_Landscape.svg"));
if (rx.indexIn(dir[i]) > -1) {
int id = rx.cap(1).toInt();
QFile file(QString::fromAscii(":/icons/actions/drawing-landscape-A0.svg"));
QAction* a = pcAction->addAction(QString());
if (file.open(QFile::ReadOnly)) {
QString s = QString::fromAscii("style=\"font-size:22px\">A%1</tspan></text>").arg(id);
QByteArray data = file.readAll();
data.replace("style=\"font-size:22px\">A0</tspan></text>", s.toAscii());
a->setIcon(Gui::BitmapFactory().pixmapFromSvg(data, QSize(24,24)));
}
QAction* a2 = pcAction->addAction(QString());
a2->setIcon(Gui::BitmapFactory().pixmap("actions/drawing-landscape-A2"));
a->setProperty("TemplateId", id);
a->setProperty("Template", dir.absoluteFilePath(dir[i]));
QAction* a3 = pcAction->addAction(QString());
a3->setIcon(Gui::BitmapFactory().pixmap("actions/drawing-landscape-A3"));
QAction* a4 = pcAction->addAction(QString());
a4->setIcon(Gui::BitmapFactory().pixmap("actions/drawing-landscape-A4"));
if (id == 3) {
defaultAction = a;
defaultId = pcAction->actions().size() - 1;
}
}
}
_pcAction = pcAction;
languageChange();
pcAction->setIcon(a3->icon());
pcAction->setProperty("defaultAction", QVariant(3));
if (defaultAction) {
pcAction->setIcon(defaultAction->icon());
pcAction->setProperty("defaultAction", QVariant(defaultId));
}
else if (!pcAction->actions().isEmpty()) {
pcAction->setIcon(pcAction->actions()[0]->icon());
pcAction->setProperty("defaultAction", QVariant(0));
}
return pcAction;
}
@ -146,41 +170,15 @@ void CmdDrawingNewPage::languageChange()
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
a[0]->setText(QCoreApplication::translate(
"Drawing_NewPage", "A0 landscape", 0,
QCoreApplication::CodecForTr));
a[0]->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A0 landscape drawing", 0,
QCoreApplication::CodecForTr));
a[1]->setText(QCoreApplication::translate(
"Drawing_NewPage", "A1 landscape", 0,
QCoreApplication::CodecForTr));
a[1]->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A1 landscape drawing", 0,
QCoreApplication::CodecForTr));
a[2]->setText(QCoreApplication::translate(
"Drawing_NewPage", "A2 landscape", 0,
QCoreApplication::CodecForTr));
a[2]->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A2 landscape drawing", 0,
QCoreApplication::CodecForTr));
a[3]->setText(QCoreApplication::translate(
"Drawing_NewPage", "A3 landscape", 0,
QCoreApplication::CodecForTr));
a[3]->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A3 landscape drawing", 0,
QCoreApplication::CodecForTr));
a[4]->setText(QCoreApplication::translate(
"Drawing_NewPage", "A4 landscape", 0,
QCoreApplication::CodecForTr));
a[4]->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A4 landscape drawing", 0,
QCoreApplication::CodecForTr));
for (QList<QAction*>::iterator it = a.begin(); it != a.end(); ++it) {
int id = (*it)->property("TemplateId").toInt();
(*it)->setText(QCoreApplication::translate(
"Drawing_NewPage", "A%1 landscape", 0,
QCoreApplication::CodecForTr).arg(id));
(*it)->setToolTip(QCoreApplication::translate(
"Drawing_NewPage", "Insert new A%1 landscape drawing", 0,
QCoreApplication::CodecForTr).arg(id));
}
}
bool CmdDrawingNewPage::isActive(void)

View File

@ -251,6 +251,14 @@
<source>Insert new A4 landscape drawing</source>
<translation>Neue A3-Zeichung einfügen (im Querformat) {4 ?}</translation>
</message>
<message>
<source>Insert new A%1 landscape drawing</source>
<translation>Neue A%1-Zeichung im Querformat einfügen</translation>
</message>
<message>
<source>A%1 landscape</source>
<translation>A%1 im Querformat</translation>
</message>
</context>
<context>
<name>QObject</name>

View File

@ -26,6 +26,7 @@
#ifndef _PreComp_
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <QMessageBox>
# include <QSet>
#endif
@ -194,10 +195,17 @@ bool FaceColors::accept()
bool FaceColors::reject()
{
Gui::Document* doc = Gui::Application::Instance->getDocument(d->vp->getObject()->getDocument());
doc->resetEdit();
d->vp->DiffuseColor.setValues(d->current);
return true;
int ret = QMessageBox::question(this, tr("Face colors"), tr("Do you really want to cancel?"),
QMessageBox::Yes, QMessageBox::No|QMessageBox::Default|QMessageBox::Escape);
if (ret == QMessageBox::Yes) {
Gui::Document* doc = Gui::Application::Instance->getDocument(d->vp->getObject()->getDocument());
doc->resetEdit();
d->vp->DiffuseColor.setValues(d->current);
return true;
}
else {
return false;
}
}
void FaceColors::changeEvent(QEvent *e)

View File

@ -2,6 +2,7 @@ SET(ShipMain_SRCS
InitGui.py
ShipGui.py
Instance.py
SimInstance.py
TankInstance.py
)
SOURCE_GROUP("" FILES ${ShipMain_SRCS})
@ -36,6 +37,14 @@ SET(ShipIcons_SRCS
Icons/Weight.png
Icons/Weight.xcf
Icons/Weight.xpm
Icons/SimIco.xcf
Icons/Sim.xpm
Icons/SimCreateIco.png
Icons/SimCreateIco.xpm
Icons/SimRunIco.png
Icons/SimRunIco.xpm
Icons/SimStopIco.png
Icons/SimStopIco.xpm
Icons/Tank.png
Icons/Tank.xcf
Icons/Tank.xpm
@ -47,6 +56,7 @@ SET(ShipExamples_SRCS
Examples/s60_katamaran.fcstd
Examples/wigley.fcstd
Examples/wigley_katamaran.fcstd
OpenCL/simInit.cl
)
SOURCE_GROUP("shipexamples" FILES ${ShipExamples_SRCS})
@ -121,9 +131,29 @@ SET(ShipGZ_SRCS
tankGZ/TaskPanel.py
tankGZ/TaskPanel.ui
)
SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_SRCS})
SOURCE_GROUP("shipgz" FILES ${ShipGZ_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS})
SET(SimCreate_SRCS
simCreate/__init__.py
simCreate/TaskPanel.py
simCreate/TaskPanel.ui
)
SOURCE_GROUP("simcreate" FILES ${SimCreate_SRCS})
SET(SimRun_SRCS
simRun/__init__.py
simRun/Simulation.py
simRun/TaskPanel.py
simRun/TaskPanel.ui
simRun/clSim/__init__.py
simRun/clSim/initialization.py
simRun/clSim/Utils.py
simRun/Sim/__init__.py
simRun/Sim/initialization.py
)
SOURCE_GROUP("simrun" FILES ${SimRun_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS})
ADD_CUSTOM_TARGET(Ship ALL
SOURCES ${all_files}
@ -197,6 +227,18 @@ INSTALL(
DESTINATION
Mod/Ship/tankGZ
)
INSTALL(
FILES
${SimCreate_SRCS}
DESTINATION
Mod/Ship/simCreate
)
INSTALL(
FILES
${SimRun_SRCS}
DESTINATION
Mod/Ship/simRun
)
INSTALL(
FILES
${ShipMain_SRCS}

336
src/Mod/Ship/Icons/Sim.xpm Normal file
View File

@ -0,0 +1,336 @@
/* XPM */
static char * Sim_xpm[] = {
"32 32 301 2",
" c None",
". c #CCCCCC",
"+ c #A9A9A9",
"@ c #989898",
"# c #A1A1A1",
"$ c #C3C3C3",
"% c #C1C0C1",
"& c #BFBFBF",
"* c #A7A7A7",
"= c #808080",
"- c #5C5C5C",
"; c #565655",
"> c #4E4E4E",
", c #676767",
"' c #898989",
") c #B6B5B6",
"! c #BABABA",
"~ c #B9B9B9",
"{ c #A5A5A5",
"] c #7E7E7E",
"^ c #595A59",
"/ c #575656",
"( c #535353",
"_ c #505050",
": c #4D4D4C",
"< c #474747",
"[ c #404040",
"} c #4D4D4D",
"| c #787878",
"1 c #B8B7B8",
"2 c #B6B6B6",
"3 c #888888",
"4 c #7C7C7C",
"5 c #575657",
"6 c #535354",
"7 c #4E4D4E",
"8 c #4A4A4A",
"9 c #444444",
"0 c #414141",
"a c #3E3E3E",
"b c #393938",
"c c #313131",
"d c #393939",
"e c #636363",
"f c #ABABAB",
"g c #B3B3B3",
"h c #848484",
"i c #787979",
"j c #545454",
"k c #515151",
"l c #4B4B4B",
"m c #484748",
"n c #3B3B3B",
"o c #383838",
"p c #353535",
"q c #323232",
"r c #2F2F2E",
"s c #2A2A2A",
"t c #222323",
"u c #252625",
"v c #AFAFAF",
"w c #767676",
"x c #484848",
"y c #454545",
"z c #424242",
"A c #3F3F3E",
"B c #3B3B3C",
"C c #393838",
"D c #2F2F2F",
"E c #2C2C2C",
"F c #292929",
"G c #262626",
"H c #222222",
"I c #1F1F20",
"J c #171716",
"K c #959595",
"L c #747474",
"M c #4E4E4F",
"N c #4C4B4C",
"O c #484849",
"P c #424243",
"Q c #282828",
"R c #525251",
"S c #373737",
"T c #353636",
"U c #333233",
"V c #30302F",
"W c #2C2D2D",
"X c #232323",
"Y c #201F20",
"Z c #1D1D1D",
"` c #151414",
" . c #717272",
".. c #4C4C4C",
"+. c #484949",
"@. c #464545",
"#. c #424343",
"$. c #3A3A3A",
"%. c #5D4A49",
"&. c #7E7E86",
"*. c #56569F",
"=. c #3E3E41",
"-. c #757575",
";. c #575757",
">. c #222221",
",. c #262627",
"'. c #242423",
"). c #212020",
"!. c #1A1A1A",
"~. c #121212",
"{. c #939493",
"]. c #6F6F6F",
"^. c #494949",
"/. c #464646",
"(. c #434343",
"_. c #554545",
":. c #686863",
"<. c #939394",
"[. c #BDBDBD",
"}. c #202021",
"|. c #1E1E1E",
"1. c #171718",
"2. c #0F0F0F",
"3. c #929292",
"4. c #6C6D6D",
"5. c #464746",
"6. c #525F73",
"7. c #444648",
"8. c #3D3D3D",
"9. c #2D2C2A",
"0. c #A1A2A2",
"a. c #AAACAC",
"b. c #A6A7A7",
"c. c #A8AAAA",
"d. c #AFB0B0",
"e. c #777676",
"f. c #9A9A9A",
"g. c #1B1B1B",
"h. c #181818",
"i. c #0C0C0C",
"j. c #909090",
"k. c #6B6A6B",
"l. c #55657E",
"m. c #6990FB",
"n. c #6483CD",
"o. c #5871B2",
"p. c #434E7E",
"q. c #A97C76",
"r. c #AB7777",
"s. c #AC7070",
"t. c #A26565",
"u. c #805C5C",
"v. c #848686",
"w. c #424342",
"x. c #151515",
"y. c #0A0909",
"z. c #8F8F8F",
"A. c #676868",
"B. c #3B3A3A",
"C. c #383738",
"D. c #353534",
"E. c #45525F",
"F. c #6367AC",
"G. c #804682",
"H. c #942A39",
"I. c #991312",
"J. c #540901",
"K. c #393742",
"L. c #1C1C1C",
"M. c #191919",
"N. c #161515",
"O. c #121313",
"P. c #070707",
"Q. c #8D8E8D",
"R. c #656566",
"S. c #3E3F3F",
"T. c #2F2E2F",
"U. c #353838",
"V. c #35496A",
"W. c #3E4D88",
"X. c #354889",
"Y. c #5573D7",
"Z. c #5D80FB",
"`. c #374899",
" + c #293338",
".+ c #101010",
"++ c #0D0D0D",
"@+ c #040404",
"#+ c #8C8C8C",
"$+ c #8B8B8B",
"%+ c #4B4A4B",
"&+ c #303030",
"*+ c #333232",
"=+ c #2F2F30",
"-+ c #232223",
";+ c #1A1919",
">+ c #2E3949",
",+ c #5C7BA3",
"'+ c #36467D",
")+ c #536F93",
"!+ c #0A0A0A",
"~+ c #010101",
"{+ c #C1C1C1",
"]+ c #B8B8B8",
"^+ c #A0A0A0",
"/+ c #3F3F3F",
"(+ c #222122",
"_+ c #202020",
":+ c #161717",
"<+ c #141414",
"[+ c #111011",
"}+ c #0D0E0E",
"|+ c #0B0B0A",
"1+ c #000000",
"2+ c #525252",
"3+ c #686868",
"4+ c #ADADAD",
"5+ c #9E9F9F",
"6+ c #6D6D6D",
"7+ c #3C3C3C",
"8+ c #131414",
"9+ c #111111",
"0+ c #0E0E0E",
"a+ c #0B0B0B",
"b+ c #080708",
"c+ c #050504",
"d+ c #4C4D4C",
"e+ c #4D4C4D",
"f+ c #494A4A",
"g+ c #454444",
"h+ c #9D9D9D",
"i+ c #9E9E9E",
"j+ c #AEAEAE",
"k+ c #BEBEBF",
"l+ c #BEBDBD",
"m+ c #979797",
"n+ c #6A6B6A",
"o+ c #3F3F40",
"p+ c #020202",
"q+ c #030303",
"r+ c #878787",
"s+ c #69696A",
"t+ c #868685",
"u+ c #646464",
"v+ c #474647",
"w+ c #656565",
"x+ c #9E9F9E",
"y+ c #A8A8A8",
"z+ c #AFAFAE",
"A+ c #A4A4A4",
"B+ c #7A7A7A",
"C+ c #969696",
"D+ c #363636",
"E+ c #777776",
"F+ c #8C8D8D",
"G+ c #7D7D7D",
"H+ c #5E5E5E",
"I+ c #4F4F50",
"J+ c #808181",
"K+ c #707070",
"L+ c #909191",
"M+ c #9C9C9C",
"N+ c #787877",
"O+ c #696969",
"P+ c #616161",
"Q+ c #6E6E6E",
"R+ c #7C7B7C",
"S+ c #777677",
"T+ c #6F6E6E",
"U+ c #595959",
"V+ c #717171",
"W+ c #8D8D8D",
"X+ c #515051",
"Y+ c #49494A",
"Z+ c #4B4A4A",
"`+ c #606060",
" @ c #6A6A6A",
".@ c #616162",
"+@ c #6C6D6C",
"@@ c #767777",
"#@ c #727272",
"$@ c #6B6B6B",
"%@ c #828283",
"&@ c #757475",
"*@ c #444545",
"=@ c #565656",
"-@ c #5A595A",
";@ c #666666",
">@ c #878687",
",@ c #8A8A8A",
"'@ c #797979",
")@ c #444344",
"!@ c #7F8080",
"~@ c #737373",
"{@ c #484747",
"]@ c #707170",
"^@ c #7F7F7F",
"/@ c #676867",
"(@ c #4D4C4C",
"_@ c #5F5F5F",
":@ c #434444",
" ",
" ",
" . + ",
" @ # $ % & * ",
" = - ; > , ' ) ! ~ { ",
" ] ^ / ( _ : < [ } | # 1 2 # 3 ",
" 4 5 6 _ 7 8 < 9 0 a b c d e ' f g + h ",
" i j k 7 l m 9 0 a n o p q r s t u < | v ",
" w k > l x y z A B C p q D E F G H I J K ",
" L M N O y P Q R S T U V W F G X Y Z ` K ",
" ...+.@.#.$.%.&.*.=.-.;.>.,.'.).Z !.~.{. ",
" ].^./.(.[ c _._ :.<.[.$ ' /.}.|.!.1.2.3. ",
" 4.5.6.7.8.9.# 0.a.b.c.d.e.f.g.g.h.` i.j. ",
" k.9 l.m.n.o.p.q.r.s.t.u.v.w.g.h.x.~.y.z. ",
" A.0 a B.C.D.E.F.G.H.I.J.K.L.M.N.O.2.P.Q. ",
" R.S.n o p q T.E U.V.W.X.Y.Z.`. +.+++@+#+ ",
" $+%+&+q *+=+E F G -+I Z ;+>+,+'+)+!+~+$+ ",
" {+]+^+w /+H (+X _+Z !.:+<+[+}+|+P.1+' ",
" k 2+_ > 3+z.4+5+6+7+x.~.8+9+0+a+b+c+1+3 ",
" %+..d+e+..f+< g+h+i+j+k+l+m+n+o+P.p+q+p+1+r+ ",
" s+t+u+< (.< v+y 9 (.w+x+y+z+y+h+A+B+C+K ].D+1+h ",
" E+i+F+f.j.G+H+9 [ (.z I+J+m+f.j.K+z 9 9 9 K+L+r+/.9 (. ",
" L M+N+O+u+P+Q+R+S+T+U+y 8 - ;...9 9 9 9 9 9 9 9 (.(.k w+ ",
" V+m+' W+r+] , X+Y+(.: r+L P+k 9 z (.9 9 9 9 (.(.Z+;.- `+ ",
" ].C+w @u+.@+@@@#@$@j %@B+&@#@L $@H+2+/.0 (.*@+.} 2+=@-@ ",
" ;@| >@,@'@u+k 8 )@..!@| ~@V+#@#@#@#@L 6+..(.9 {@.._ ( ",
" e ]@^@] /@k G+w #@#@#@#@#@V+ @$@_ 9 9 9 /.Y+(@ ",
" - R.T+L ~@#@#@#@#@]._ _@_ 9 9 9 (.9 x ",
" =@_@O+L ~@#@~@L _ 9 9 :@ ",
" ;.H+ @-._ (. ",
" ",
" "};

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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because it is too large Load Diff

View File

@ -31,16 +31,38 @@ class ShipWorkbench ( Workbench ):
ToolTip = str(Translator.translate("Ship design"))
def Initialize(self):
from shipUtils import Translator
# ToolBar
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
self.appendToolbar("Ship design",list)
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
self.appendToolbar("Loading",list)
self.appendToolbar("Weights",list)
# Simulation stuff only if pyOpenCL & numpy are present
hasOpenCL = True
hasNumpy = True
try:
import pyopencl
except ImportError:
hasOpenCL = False
msg = Translator.translate("pyOpenCL not installed, ship simulations disabled\n")
App.Console.PrintWarning(msg)
try:
import numpy
except ImportError:
hasNumpy = False
msg = Translator.translate("numpy not installed, ship simulations disabled\n")
App.Console.PrintWarning(msg)
if hasOpenCL and hasNumpy:
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim"]
self.appendToolbar("Simulation",list)
# Menu
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
self.appendMenu("Ship design",list)
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
self.appendToolbar("Loading",list)
self.appendMenu("Weights",list)
if hasOpenCL and hasNumpy:
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim"]
self.appendMenu("Simulation",list)
Gui.addWorkbench(ShipWorkbench())

View File

@ -30,7 +30,8 @@ from pivy import coin
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base, Vector
from FreeCAD import Base, Vector
import Part
# Ship design module
from shipUtils import Paths, Translator, Math

View File

@ -5,6 +5,7 @@ data_DATA = \
InitGui.py \
ShipGui.py \
Instance.py \
SimInstance.py \
TankInstance.py
nobase_data_DATA = \
@ -37,6 +38,14 @@ nobase_data_DATA = \
Icons/Weight.png \
Icons/Weight.xcf \
Icons/Weight.xpm \
Icons/SimIco.xcf \
Icons/Sim.xpm \
Icons/SimCreateIco.png \
Icons/SimCreateIco.xpm \
Icons/SimRunIco.png \
Icons/SimRunIco.xpm \
Icons/SimStopIco.png \
Icons/SimStopIco.xpm \
Icons/Tank.png \
Icons/Tank.xcf \
Icons/Tank.xpm \
@ -44,6 +53,7 @@ nobase_data_DATA = \
Examples/s60_katamaran.fcstd \
Examples/wigley.fcstd \
Examples/wigley_katamaran.fcstd \
OpenCL/simInit.cl \
shipLoadExample/__init__.py \
shipLoadExample/TaskPanel.py \
shipLoadExample/TaskPanel.ui \
@ -80,7 +90,19 @@ nobase_data_DATA = \
tankGZ/__init__.py \
tankGZ/Plot.py \
tankGZ/TaskPanel.py \
tankGZ/TaskPanel.ui
tankGZ/TaskPanel.ui \
simCreate/__init__.py \
simCreate/TaskPanel.py \
simCreate/TaskPanel.ui \
simRun/__init__.py \
simRun/Simulation.py \
simRun/TaskPanel.py \
simRun/TaskPanel.ui \
simRun/clSim/__init__.py \
simRun/clSim/initialization.py \
simRun/clSim/Utils.py \
simRun/Sim/__init__.py \
simRun/Sim/initialization.py
CLEANFILES = $(BUILT_SOURCES)

View File

@ -0,0 +1,99 @@
/*
* -----------------------------------------------------------------------
*
* This source file is part of AQUA-gpusph.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
*
*
* Authors:
* - Cercos Pita, Jose Luis
* - Miguel Gonzalez, Leo
* - Saelices, Jaime
* - Souto Iglesias, Antonio
*
* -----------------------------------------------------------------------
*/
#ifndef M_PI
#define M_PI 3,14159265359
#endif
#ifdef _g
#error '_g' is already defined.
#endif
#define _g __global
#ifdef _l
#error '_l' is already defined.
#endif
#define _l __local
#ifdef _c
#error '_c' is already defined.
#endif
#define _c __constant
#ifndef _grav
#define _grav 9.81
#endif
/** Setup velocity and acceleration potential for initial time step.
* @param pos Cell position.
* @param v Cell velocity.
* @param f Cell acceleration.
* @param waves Waves (A,T,phase,heading)
* @param phi Velocity potential.
* @param Phi Acceleration potential
* @param N Number of cell elements at each direction.
* @param n Number of waves.
*/
__kernel void FS(_g float4* pos, _g float4* v, _g float4* f,
_g float4* waves, _g float* phi, _g float* Phi,
uint2 N, uint n)
{
// find position in global arrays
unsigned int i = get_global_id(0);
unsigned int j = get_global_id(1);
if( (i >= N.x) || (j >= N.y) )
return;
unsigned int id = i*N.y + j;
// ---- | ------------------------ | ----
// ---- V ---- Your code here ---- V ----
unsigned int w;
for(w=0;w<n;w++){
float A = waves[w].x;
float T = waves[w].y;
float phase = waves[w].z;
float heading = M_PI*waves[w].w/180.f;
float lambda = 0.5f*_grav/M_PI * T*T;
float k = 2.f*M_PI/lambda;
float frec = 2.f*M_PI/T;
float l = pos[id].x*cos(heading) + pos[id].y*sin(heading);
// Position, velocity and acceleration
float amp = A*sin(k*l + phase);
pos[id].z = amp;
v[id].z = -frec*amp;
f[id].z = frec*frec*amp;
// Potentials
phi[id] = _grav/frec*amp;
Phi[id] = -_grav*amp;
}
// ---- A ---- Your code here ---- A ----
// ---- | ------------------------ | ----
}

View File

@ -120,6 +120,42 @@ class GZ:
ToolTip = str(Translator.translate('Transversal stability GZ curve computation'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class CreateSim:
def Activated(self):
import simCreate
simCreate.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/SimCreateIco.png"
MenuText = str(Translator.translate('Create a new simulation'))
ToolTip = str(Translator.translate('Create a new simulation in order to process later'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class RunSim:
def Activated(self):
import simRun
simRun.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/SimRunIco.png"
MenuText = str(Translator.translate('Run a simulation'))
ToolTip = str(Translator.translate('Run a simulation'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class StopSim:
def Activated(self):
import simRun
simRun.stop()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/SimStopIco.png"
MenuText = str(Translator.translate('Stop active simulation'))
ToolTip = str(Translator.translate('Stop active simulation'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
FreeCADGui.addCommand('Ship_LoadExample', LoadExample())
FreeCADGui.addCommand('Ship_CreateShip', CreateShip())
FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw())
@ -128,3 +164,6 @@ FreeCADGui.addCommand('Ship_Hydrostatics', Hydrostatics())
FreeCADGui.addCommand('Ship_Weights', SetWeights())
FreeCADGui.addCommand('Ship_CreateTank', CreateTank())
FreeCADGui.addCommand('Ship_GZ', GZ())
FreeCADGui.addCommand('Ship_CreateSim', CreateSim())
FreeCADGui.addCommand('Ship_RunSim', RunSim())
FreeCADGui.addCommand('Ship_StopSim', StopSim())

657
src/Mod/Ship/SimInstance.py Normal file
View File

@ -0,0 +1,657 @@
#***************************************************************************
#* *
#* 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
from math import *
import threading
# COIN
from pivy.coin import *
from pivy import coin
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Base, Vector
import Part
# Ship design module
from shipUtils import Paths, Translator, Math
class FreeSurfaceFace:
def __init__(self, pos, normal, l, b):
""" Face storage.
@param pos Face position.
@param normal Face normal.
@param l Element length (distance between elements at x direction)
@param b Element beam (distance between elements at y direction)
"""
self.pos = pos
self.normal = normal
self.area = l*b
def __init__(self, pos, normal, area):
""" Face storage.
@param pos Face position.
@param normal Face normal.
@param area Element area
"""
self.pos = pos
self.normal = normal
self.area = area
class ShipSimulation:
def __init__(self, obj, fsMeshData, waves):
""" Creates a new simulation instance on active document.
@param obj Created Part::FeaturePython object.
@param fsMeshData [L,B,N] Free surface mesh data, with lenght
(x), Beam (y) and desired number of points.
@param waves [[A,T,phi,heading],] Waves involved
"""
# Add uniqueness property to identify Tank instances
obj.addProperty("App::PropertyBool","IsShipSimulation","ShipSimulation", str(Translator.translate("True if is a valid ship simulation instance"))).IsShipSimulation=True
# Compute free surface mesh
self.createFSMesh(obj,fsMeshData)
# Store waves
obj.addProperty("App::PropertyVectorList","Waves","ShipSimulation", str(Translator.translate("Waves (Amplitude,period,phase)"))).Waves=[]
obj.addProperty("App::PropertyFloatList","Waves_Dir","ShipSimulation", str(Translator.translate("Waves direction (0 deg to stern waves)"))).Waves_Dir=[]
w = []
d = []
for i in range(0,len(waves)):
w.append(Vector(waves[i][0], waves[i][1], waves[i][2]))
d.append(waves[i][3])
obj.Waves = w
obj.Waves_Dir = d
# Add shapes
shape = self.computeShape(obj)
if not shape:
obj.IsShipSimulation=False
return
obj.Shape = shape
obj.Proxy = self
def onChanged(self, fp, prop):
""" Property changed, tank must be recomputed """
if prop == "IsShipSimulation":
FreeCAD.Console.PrintWarning("Ussually you don't want to modify manually this option.\n")
def execute(self, obj):
""" Shape recomputation called """
obj.Shape = self.computeShape(obj)
def createFSMesh(self, obj, fsMeshData):
""" Create or modify free surface mesh.
@param obj Created Part::FeaturePython object.
@param fsMeshData [L,B,N] Free surface mesh data, with lenght
(x), Beam (y) and desired number of points.
"""
# Study input object
try:
props = obj.PropertiesList
props.index("IsShipSimulation")
if not obj.IsShipSimulation:
msg = str(Translator.translate("Object is not a valid ship simulation.\n"))
FreeCAD.Console.PrintError(msg)
return
except ValueError:
msg = str(Translator.translate("Object is not a ship simulation.\n"))
FreeCAD.Console.PrintError(msg)
return
# Get areas and number of elements per direction
L = fsMeshData[0]
B = fsMeshData[1]
N = fsMeshData[2]
A = L*B
area = A/N
l = sqrt(area)
b = sqrt(area)
nx = int(round(L / l))
ny = int(round(B / b))
# Start data fields if not already exist
props = obj.PropertiesList
try:
props.index("FS_Nx")
except ValueError:
obj.addProperty("App::PropertyInteger","FS_Nx","ShipSimulation", str(Translator.translate("Free surface number of elements at x direction"))).FS_Nx=0
try:
props.index("FS_Ny")
except ValueError:
obj.addProperty("App::PropertyInteger","FS_Ny","ShipSimulation", str(Translator.translate("Free surface number of elements at y direction"))).FS_Ny=0
try:
props.index("FS_Position")
except ValueError:
obj.addProperty("App::PropertyVectorList","FS_Position","ShipSimulation", str(Translator.translate("Free surface elements position"))).FS_Position=[]
try:
props.index("FS_Area")
except ValueError:
obj.addProperty("App::PropertyFloatList","FS_Area","ShipSimulation", str(Translator.translate("Free surface elements area"))).FS_Area=[]
try:
props.index("FS_Normal")
except ValueError:
obj.addProperty("App::PropertyVectorList","FS_Normal","ShipSimulation", str(Translator.translate("Free surface elements normal"))).FS_Normal=[]
# Fill data
obj.FS_Nx = nx
obj.FS_Ny = ny
pos = []
areas = []
normal = []
for i in range(0,nx):
for j in range(0,ny):
pos.append(Vector(-0.5*L + (i+0.5)*l,-0.5*B + (j+0.5)*b,0.0))
areas.append(l*b)
normal.append(Vector(0.0,0.0,1.0))
obj.FS_Position = pos[:]
obj.FS_Area = areas[:]
obj.FS_Normal = normal[:]
def computeShape(self, obj):
""" Computes simulation involved shapes.
@param obj Created Part::FeaturePython object.
@return Shape
"""
print("[ShipSimulation] Computing mesh shape...")
nx = obj.FS_Nx
ny = obj.FS_Ny
mesh = FSMesh(obj)
planes = []
# Create planes
Percentage = 0
Count = 0
print("0%")
for i in range(1,nx-1):
for j in range(1,ny-1):
Count = Count+1
done = int(round(100 * Count / ((nx-2)*(ny-2))))
if done != Percentage:
Percentage = done
print("%i%%" % (done))
v0 = (mesh[i][j].pos + mesh[i-1][j].pos + mesh[i][j-1].pos + mesh[i-1][j-1].pos).multiply(0.25)
v1 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j-1].pos + mesh[i+1][j-1].pos).multiply(0.25)
v2 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j+1].pos + mesh[i+1][j+1].pos).multiply(0.25)
v3 = (mesh[i][j].pos + mesh[i-1][j].pos + mesh[i][j+1].pos + mesh[i-1][j+1].pos).multiply(0.25)
p = Part.makePolygon([v0,v1,v2,v3,v0])
planes.append(Part.makeFilledFace(p.Edges))
# Join into a compound
return Part.makeCompound(planes)
class ViewProviderShipSimulation:
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 "Flat Lines"
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 * Sim_xpm[] = {
"32 32 301 2",
" c None",
". c #CCCCCC",
"+ c #A9A9A9",
"@ c #989898",
"# c #A1A1A1",
"$ c #C3C3C3",
"% c #C1C0C1",
"& c #BFBFBF",
"* c #A7A7A7",
"= c #808080",
"- c #5C5C5C",
"; c #565655",
"> c #4E4E4E",
", c #676767",
"' c #898989",
") c #B6B5B6",
"! c #BABABA",
"~ c #B9B9B9",
"{ c #A5A5A5",
"] c #7E7E7E",
"^ c #595A59",
"/ c #575656",
"( c #535353",
"_ c #505050",
": c #4D4D4C",
"< c #474747",
"[ c #404040",
"} c #4D4D4D",
"| c #787878",
"1 c #B8B7B8",
"2 c #B6B6B6",
"3 c #888888",
"4 c #7C7C7C",
"5 c #575657",
"6 c #535354",
"7 c #4E4D4E",
"8 c #4A4A4A",
"9 c #444444",
"0 c #414141",
"a c #3E3E3E",
"b c #393938",
"c c #313131",
"d c #393939",
"e c #636363",
"f c #ABABAB",
"g c #B3B3B3",
"h c #848484",
"i c #787979",
"j c #545454",
"k c #515151",
"l c #4B4B4B",
"m c #484748",
"n c #3B3B3B",
"o c #383838",
"p c #353535",
"q c #323232",
"r c #2F2F2E",
"s c #2A2A2A",
"t c #222323",
"u c #252625",
"v c #AFAFAF",
"w c #767676",
"x c #484848",
"y c #454545",
"z c #424242",
"A c #3F3F3E",
"B c #3B3B3C",
"C c #393838",
"D c #2F2F2F",
"E c #2C2C2C",
"F c #292929",
"G c #262626",
"H c #222222",
"I c #1F1F20",
"J c #171716",
"K c #959595",
"L c #747474",
"M c #4E4E4F",
"N c #4C4B4C",
"O c #484849",
"P c #424243",
"Q c #282828",
"R c #525251",
"S c #373737",
"T c #353636",
"U c #333233",
"V c #30302F",
"W c #2C2D2D",
"X c #232323",
"Y c #201F20",
"Z c #1D1D1D",
"` c #151414",
" . c #717272",
".. c #4C4C4C",
"+. c #484949",
"@. c #464545",
"#. c #424343",
"$. c #3A3A3A",
"%. c #5D4A49",
"&. c #7E7E86",
"*. c #56569F",
"=. c #3E3E41",
"-. c #757575",
";. c #575757",
">. c #222221",
",. c #262627",
"'. c #242423",
"). c #212020",
"!. c #1A1A1A",
"~. c #121212",
"{. c #939493",
"]. c #6F6F6F",
"^. c #494949",
"/. c #464646",
"(. c #434343",
"_. c #554545",
":. c #686863",
"<. c #939394",
"[. c #BDBDBD",
"}. c #202021",
"|. c #1E1E1E",
"1. c #171718",
"2. c #0F0F0F",
"3. c #929292",
"4. c #6C6D6D",
"5. c #464746",
"6. c #525F73",
"7. c #444648",
"8. c #3D3D3D",
"9. c #2D2C2A",
"0. c #A1A2A2",
"a. c #AAACAC",
"b. c #A6A7A7",
"c. c #A8AAAA",
"d. c #AFB0B0",
"e. c #777676",
"f. c #9A9A9A",
"g. c #1B1B1B",
"h. c #181818",
"i. c #0C0C0C",
"j. c #909090",
"k. c #6B6A6B",
"l. c #55657E",
"m. c #6990FB",
"n. c #6483CD",
"o. c #5871B2",
"p. c #434E7E",
"q. c #A97C76",
"r. c #AB7777",
"s. c #AC7070",
"t. c #A26565",
"u. c #805C5C",
"v. c #848686",
"w. c #424342",
"x. c #151515",
"y. c #0A0909",
"z. c #8F8F8F",
"A. c #676868",
"B. c #3B3A3A",
"C. c #383738",
"D. c #353534",
"E. c #45525F",
"F. c #6367AC",
"G. c #804682",
"H. c #942A39",
"I. c #991312",
"J. c #540901",
"K. c #393742",
"L. c #1C1C1C",
"M. c #191919",
"N. c #161515",
"O. c #121313",
"P. c #070707",
"Q. c #8D8E8D",
"R. c #656566",
"S. c #3E3F3F",
"T. c #2F2E2F",
"U. c #353838",
"V. c #35496A",
"W. c #3E4D88",
"X. c #354889",
"Y. c #5573D7",
"Z. c #5D80FB",
"`. c #374899",
" + c #293338",
".+ c #101010",
"++ c #0D0D0D",
"@+ c #040404",
"#+ c #8C8C8C",
"$+ c #8B8B8B",
"%+ c #4B4A4B",
"&+ c #303030",
"*+ c #333232",
"=+ c #2F2F30",
"-+ c #232223",
";+ c #1A1919",
">+ c #2E3949",
",+ c #5C7BA3",
"'+ c #36467D",
")+ c #536F93",
"!+ c #0A0A0A",
"~+ c #010101",
"{+ c #C1C1C1",
"]+ c #B8B8B8",
"^+ c #A0A0A0",
"/+ c #3F3F3F",
"(+ c #222122",
"_+ c #202020",
":+ c #161717",
"<+ c #141414",
"[+ c #111011",
"}+ c #0D0E0E",
"|+ c #0B0B0A",
"1+ c #000000",
"2+ c #525252",
"3+ c #686868",
"4+ c #ADADAD",
"5+ c #9E9F9F",
"6+ c #6D6D6D",
"7+ c #3C3C3C",
"8+ c #131414",
"9+ c #111111",
"0+ c #0E0E0E",
"a+ c #0B0B0B",
"b+ c #080708",
"c+ c #050504",
"d+ c #4C4D4C",
"e+ c #4D4C4D",
"f+ c #494A4A",
"g+ c #454444",
"h+ c #9D9D9D",
"i+ c #9E9E9E",
"j+ c #AEAEAE",
"k+ c #BEBEBF",
"l+ c #BEBDBD",
"m+ c #979797",
"n+ c #6A6B6A",
"o+ c #3F3F40",
"p+ c #020202",
"q+ c #030303",
"r+ c #878787",
"s+ c #69696A",
"t+ c #868685",
"u+ c #646464",
"v+ c #474647",
"w+ c #656565",
"x+ c #9E9F9E",
"y+ c #A8A8A8",
"z+ c #AFAFAE",
"A+ c #A4A4A4",
"B+ c #7A7A7A",
"C+ c #969696",
"D+ c #363636",
"E+ c #777776",
"F+ c #8C8D8D",
"G+ c #7D7D7D",
"H+ c #5E5E5E",
"I+ c #4F4F50",
"J+ c #808181",
"K+ c #707070",
"L+ c #909191",
"M+ c #9C9C9C",
"N+ c #787877",
"O+ c #696969",
"P+ c #616161",
"Q+ c #6E6E6E",
"R+ c #7C7B7C",
"S+ c #777677",
"T+ c #6F6E6E",
"U+ c #595959",
"V+ c #717171",
"W+ c #8D8D8D",
"X+ c #515051",
"Y+ c #49494A",
"Z+ c #4B4A4A",
"`+ c #606060",
" @ c #6A6A6A",
".@ c #616162",
"+@ c #6C6D6C",
"@@ c #767777",
"#@ c #727272",
"$@ c #6B6B6B",
"%@ c #828283",
"&@ c #757475",
"*@ c #444545",
"=@ c #565656",
"-@ c #5A595A",
";@ c #666666",
">@ c #878687",
",@ c #8A8A8A",
"'@ c #797979",
")@ c #444344",
"!@ c #7F8080",
"~@ c #737373",
"{@ c #484747",
"]@ c #707170",
"^@ c #7F7F7F",
"/@ c #676867",
"(@ c #4D4C4C",
"_@ c #5F5F5F",
":@ c #434444",
" ",
" ",
" . + ",
" @ # $ % & * ",
" = - ; > , ' ) ! ~ { ",
" ] ^ / ( _ : < [ } | # 1 2 # 3 ",
" 4 5 6 _ 7 8 < 9 0 a b c d e ' f g + h ",
" i j k 7 l m 9 0 a n o p q r s t u < | v ",
" w k > l x y z A B C p q D E F G H I J K ",
" L M N O y P Q R S T U V W F G X Y Z ` K ",
" ...+.@.#.$.%.&.*.=.-.;.>.,.'.).Z !.~.{. ",
" ].^./.(.[ c _._ :.<.[.$ ' /.}.|.!.1.2.3. ",
" 4.5.6.7.8.9.# 0.a.b.c.d.e.f.g.g.h.` i.j. ",
" k.9 l.m.n.o.p.q.r.s.t.u.v.w.g.h.x.~.y.z. ",
" A.0 a B.C.D.E.F.G.H.I.J.K.L.M.N.O.2.P.Q. ",
" R.S.n o p q T.E U.V.W.X.Y.Z.`. +.+++@+#+ ",
" $+%+&+q *+=+E F G -+I Z ;+>+,+'+)+!+~+$+ ",
" {+]+^+w /+H (+X _+Z !.:+<+[+}+|+P.1+' ",
" k 2+_ > 3+z.4+5+6+7+x.~.8+9+0+a+b+c+1+3 ",
" %+..d+e+..f+< g+h+i+j+k+l+m+n+o+P.p+q+p+1+r+ ",
" s+t+u+< (.< v+y 9 (.w+x+y+z+y+h+A+B+C+K ].D+1+h ",
" E+i+F+f.j.G+H+9 [ (.z I+J+m+f.j.K+z 9 9 9 K+L+r+/.9 (. ",
" L M+N+O+u+P+Q+R+S+T+U+y 8 - ;...9 9 9 9 9 9 9 9 (.(.k w+ ",
" V+m+' W+r+] , X+Y+(.: r+L P+k 9 z (.9 9 9 9 (.(.Z+;.- `+ ",
" ].C+w @u+.@+@@@#@$@j %@B+&@#@L $@H+2+/.0 (.*@+.} 2+=@-@ ",
" ;@| >@,@'@u+k 8 )@..!@| ~@V+#@#@#@#@L 6+..(.9 {@.._ ( ",
" e ]@^@] /@k G+w #@#@#@#@#@V+ @$@_ 9 9 9 /.Y+(@ ",
" - R.T+L ~@#@#@#@#@]._ _@_ 9 9 9 (.9 x ",
" =@_@O+L ~@#@~@L _ 9 9 :@ ",
" ;.H+ @-._ (. ",
" ",
" "};
"""
def FSMesh(obj, recompute=False):
""" Get free surface mesh in matrix mode.
@param obj Created Part::FeaturePython object.
@param recompute True if mesh must be recomputed, False otherwise.
@return Faces matrix
"""
nx = obj.FS_Nx
ny = obj.FS_Ny
if not recompute:
faces = []
for i in range(0,nx):
faces.append([])
for j in range(0,ny):
faces[i].append(FreeSurfaceFace(obj.FS_Position[j + i*ny],
obj.FS_Normal[j + i*ny],
obj.FS_Area[j + i*ny]))
return faces
# Transform positions into a mesh
pos = []
for i in range(0,nx):
pos.append([])
for j in range(0,ny):
pos[i].append(obj.FS_Position[j + i*ny])
# Recompute normals and dimensions
normal = []
l = []
b = []
for i in range(0,nx):
normal.append([])
l.append([])
b.append([])
for j in range(0,ny):
i0 = i-1
i1 = i+1
fi = 1.0
j0 = j-1
j1 = j+1
fj = 1.0
if i == 0:
i0 = i
i1 = i+1
fi = 2.0
if i == nx-1:
i0 = i-1
i1 = i
fi = 2.0
if j == 0:
j0 = j
j1 = j+1
fj = 2.0
if j == ny-1:
j0 = j-1
j1 = j
fj = 2.0
l[i].append(fi*(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x))
b[i].append(fj*(obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y))
xvec = Vector(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x,
obj.FS_Position[j + i1*ny].y - obj.FS_Position[j + i0*ny].y,
obj.FS_Position[j + i1*ny].z - obj.FS_Position[j + i0*ny].z)
yvec = Vector(obj.FS_Position[j1 + i*ny].x - obj.FS_Position[j0 + i*ny].x,
obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y,
obj.FS_Position[j1 + i*ny].z - obj.FS_Position[j0 + i*ny].z)
n = Vector(xvec.cross(yvec)) # Z positive
normal[i].append(n.normalize())
# Create faces
faces = []
for i in range(0,nx):
faces.append([])
for j in range(0,ny):
faces[i].append(FreeSurfaceFace(pos[i][j], normal[i][j], l[i][j], b[i][j]))
# Reconstruct mesh data
for i in range(0,nx):
for j in range(0,ny):
obj.FS_Position[j + i*ny] = faces[i][j].pos
obj.FS_Normal[j + i*ny] = faces[i][j].normal
obj.FS_Area[j + i*ny] = faces[i][j].area
return faces

View File

@ -29,7 +29,8 @@ from pivy import coin
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base, Vector
from FreeCAD import Base, Vector
import Part
# Ship design module
from shipUtils import Paths, Translator, Math

View File

@ -24,8 +24,7 @@
import os
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base
from FreeCAD import Image, ImageGui
from FreeCAD import Base, Image, ImageGui
# FreeCADShip modules
from shipUtils import Paths, Translator

View File

@ -24,7 +24,7 @@
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator

View File

@ -24,7 +24,7 @@
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator

View File

@ -25,8 +25,9 @@ import os
import math
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base, Vector
from FreeCAD import Base, Vector
from FreeCAD import Image, ImageGui
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator
import Tools

View File

@ -31,7 +31,6 @@ from PyQt4 import QtGui,QtCore
import Plot
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry
import Tools
class TaskPanel:
@ -45,7 +44,7 @@ class TaskPanel:
self.save()
draft = self.form.minDraft.value()
drafts = [draft]
dDraft = (self.form.maxDraft.value() - self.form.minDraft.value())/self.form.nDraft.value()
dDraft = (self.form.maxDraft.value() - self.form.minDraft.value())/(self.form.nDraft.value()-1)
for i in range(1,self.form.nDraft.value()):
draft = draft + dDraft
drafts.append(draft)
@ -108,7 +107,7 @@ class TaskPanel:
""" Set initial values for fields
"""
# Get objects
selObjs = Geometry.getSelectedObjs()
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
App.Console.PrintError(msg)

View File

@ -190,7 +190,7 @@
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
<number>2</number>
</property>
<property name="maximum">
<number>9999</number>

View File

@ -23,7 +23,8 @@
import math
# FreeCAD modules
from FreeCAD import Vector, Part
from FreeCAD import Vector
import Part
import FreeCAD as App
import FreeCADGui as Gui
# Module
@ -279,9 +280,9 @@ def FloatingArea(ship, draft, trim):
# Valid face, compute area
area = area + f.Area
maxX = max(maxX, faceBounds.XMax)
minX = max(minX, faceBounds.XMin)
minX = min(minX, faceBounds.XMin)
maxY = max(maxY, faceBounds.YMax)
minY = max(minY, faceBounds.YMin)
minY = min(minY, faceBounds.YMin)
# Destroy last object generated
App.ActiveDocument.removeObject(App.ActiveDocument.Objects[-1].Name)
dx = maxX - minX
@ -306,13 +307,13 @@ def BMT(ship, draft, trim=0.0):
B1 = displacement(ship,draft,roll,trim,0.0)[1]
# * M
# / \
# / \ BM ==|> BM = (BB/2) / tan(alpha/2)
# / \ BM ==|> BM = (BB/2) / sin(alpha/2)
# / \
# *-------*
# BB
BB = [B1.x - B0.x, B1.y - B0.y]
BB = [B1.y - B0.y, B1.z - B0.z]
BB = math.sqrt(BB[0]*BB[0] + BB[1]*BB[1])
BM = BM + 0.5*BB/math.tan(math.radians(0.5*roll)) / nRoll # nRoll is the weight function
BM = BM + 0.5*BB/math.sin(math.radians(0.5*roll)) / nRoll # nRoll is the weight function
return BM
def mainFrameCoeff(ship, draft):
@ -416,7 +417,7 @@ class Point:
self.wet = wet
self.farea = farea[0]
self.mom = mom
self.KBt = dispData[1].y
self.KBt = dispData[1].z
self.BMt = bm
self.Cb = dispData[2]
self.Cf = farea[1]

View File

@ -23,7 +23,8 @@
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base, Part, Vector
from FreeCAD import Base, Vector
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator
from surfUtils import Geometry

View File

@ -23,7 +23,8 @@
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base, Part, Vector
from FreeCAD import Base, Vector
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator

Binary file not shown.

Binary file not shown.

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 *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import SimInstance
from shipUtils import Paths, Translator
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/simCreate/TaskPanel.ui"
def accept(self):
form = self.form
# Read waves data
w = []
for i in range(0,form.waves.rowCount() - 1):
item = form.waves.item(i,0)
A = item.text().toFloat()[0]
item = form.waves.item(i,1)
T = item.text().toFloat()[0]
item = form.waves.item(i,2)
phi = item.text().toFloat()[0]
item = form.waves.item(i,3)
head = item.text().toFloat()[0]
w.append([A,T,phi,head])
obj = App.ActiveDocument.addObject("Part::FeaturePython","ShipSimulation")
sim = SimInstance.ShipSimulation(obj,
[form.length.value(), form.beam.value(), form.n.value()],
w)
SimInstance.ViewProviderShipSimulation(obj.ViewObject)
return True
def reject(self):
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.n = form.findChild(QtGui.QSpinBox, "N")
form.waves = form.findChild(QtGui.QTableWidget, "Waves")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
QtCore.QObject.connect(form.n, QtCore.SIGNAL("valueChanged(int)"), self.onFS)
QtCore.QObject.connect(form.waves,QtCore.SIGNAL("cellChanged(int,int)"),self.onWaves);
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
"""
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 simulation"))
self.form.findChild(QtGui.QGroupBox, "FSDataBox").setTitle(Translator.translate("Free surface"))
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, "NLabel").setText(Translator.translate("Number of points"))
self.form.findChild(QtGui.QGroupBox, "WavesDataBox").setTitle(Translator.translate("Waves"))
labels = []
labels.append(Translator.translate("Amplitude") + " [m]")
labels.append(Translator.translate("Period") + " [s]")
labels.append(Translator.translate("Phase") + " [rad]")
labels.append(Translator.translate("Heading") + " [deg]")
self.form.waves.setHorizontalHeaderLabels(labels)
def onFS(self, value):
""" Method called when free surface data is changed.
@param value Changed value.
"""
pass
def onWaves(self, row, column):
""" Method called when waves data is changed.
@param row Affected row.
@param col Affected column.
"""
item = self.form.waves.item(row,column)
# Row deletion
if column == 0:
if not item.text():
self.form.waves.removeRow(row)
# Ensure that exist one empty item at the end
nRow = self.form.waves.rowCount()
last = self.form.waves.item(nRow-1,0)
if last:
if(last.text() != ''):
self.form.waves.setRowCount(nRow+1)
# Fields must be numbers
for i in range(0,self.form.waves.rowCount()-1): # Avoid last row
for j in range(0,self.form.waves.columnCount()): # Avoid name column
item = self.form.waves.item(i,j)
if not item:
item = QtGui.QTableWidgetItem('0.0')
self.form.waves.setItem(i,j,item)
continue
(number,flag) = item.text().toFloat()
if not flag:
item.setText('0.0')
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@ -0,0 +1,269 @@
<?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>269</width>
<height>384</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>384</height>
</size>
</property>
<property name="windowTitle">
<string>Create new simulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QGroupBox" name="FSDataBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>128</height>
</size>
</property>
<property name="title">
<string>Free surface</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</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>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</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="BeamLabel">
<property name="text">
<string>Beam</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Beam">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</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="NLabel">
<property name="text">
<string>Number of points</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="N">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="WavesDataBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Waves</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QTableWidget" name="Waves">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rowCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<row/>
<column>
<property name="text">
<string>Amplitude [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Period [s]</string>
</property>
</column>
<column>
<property name="text">
<string>Phase [rad]</string>
</property>
</column>
<column>
<property name="text">
<string>Heading [deg]</string>
</property>
</column>
</widget>
</item>
</layout>
</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,24 @@
#***************************************************************************
#* *
#* 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 initialization

View File

@ -0,0 +1,114 @@
#***************************************************************************
#* *
#* 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 *
#* *
#***************************************************************************
# numpy
import numpy as np
grav=9.81
class perform:
def __init__(self, FSmesh, waves, context=None, queue=None):
""" Constructor, includes program loading.
@param FSmesh Initial free surface mesh.
@param waves Considered simulation waves (A,T,phi,heading).
@param context OpenCL context where apply. Only for compatibility,
must be None.
@param queue OpenCL command queue. Only for compatibility,
must be None.
"""
self.context = context
self.queue = queue
self.loadData(FSmesh, waves)
self.execute()
def loadData(self, FSmesh, waves):
""" Convert data to numpy format.
@param FSmesh Initial free surface mesh.
@param waves Considered simulation waves (A,T,phi,heading).
"""
nx = len(FSmesh)
ny = len(FSmesh[0])
nW = len(waves)
# Mesh data
p = np.ndarray((nx,ny, 3), dtype=np.float32)
v = np.ndarray((nx,ny, 3), dtype=np.float32)
f = np.ndarray((nx,ny, 3), dtype=np.float32)
n = np.ndarray((nx,ny, 3), dtype=np.float32)
a = np.ndarray((nx,ny, 1), dtype=np.float32)
phi = np.ndarray((nx,ny, 1), dtype=np.float32)
Phi = np.ndarray((nx,ny, 1), dtype=np.float32)
for i in range(0, nx):
for j in range(0, ny):
pos = FSmesh[i][j].pos
normal = FSmesh[i][j].normal
area = FSmesh[i][j].area
p[i,j,0] = pos.x
p[i,j,1] = pos.y
p[i,j,2] = pos.z
v[i,j,0] = 0.
v[i,j,1] = 0.
v[i,j,2] = 0.
f[i,j,0] = 0.
f[i,j,1] = 0.
f[i,j,2] = 0.
n[i,j,0] = normal.x
n[i,j,1] = normal.y
n[i,j,2] = normal.z
a[i,j] = area
self.fs = {'Nx':nx, 'Ny':ny, 'pos':p, 'vel':v, 'acc':f, \
'normal':n, 'area':a, 'velPot':phi, 'accPot':Phi}
# Waves data
w = np.ndarray((nW, 4), dtype=np.float32)
for i in range(0,nW):
w[i,0] = waves[i][0]
w[i,1] = waves[i][1]
w[i,2] = waves[i][2]
w[i,3] = waves[i][3]
self.waves = {'N':nW, 'data':w}
def execute(self):
""" Compute initial conditions. """
nx = self.fs['Nx']
ny = self.fs['Ny']
for i in range(0,nx):
for j in range(0,ny):
for w in self.waves['data']:
A = w[0]
T = w[1]
phase = w[2]
heading = np.pi*w[3]/180.0
wl = 0.5 * grav / np.pi * T*T
k = 2.0*np.pi/wl
frec = 2.0*np.pi/T
pos = self.fs['pos'][i,j]
l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading)
amp = A*np.sin(k*l + phase)
self.fs['pos'][i,j][2] = self.fs['pos'][i,j][2] + amp
amp = frec*A*np.cos(k*l + phase)
self.fs['vel'][i,j][2] = self.fs['vel'][i,j][2] - amp
amp = frec*frec*A*np.sin(k*l + phase)
self.fs['acc'][i,j][2] = self.fs['acc'][i,j][2] - amp
amp = grav/frec*A*np.sin(k*l + phase)
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + amp
amp = grav*A*np.cos(k*l + phase)
self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + amp

View File

@ -0,0 +1,110 @@
#***************************************************************************
#* *
#* 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
from math import *
import threading
# pyOpenCL
import pyopencl as cl
import numpy as np
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Base, Vector
import Part
# Ship design module
from shipUtils import Paths, Translator, Math
class Singleton(type):
def __init__(cls, name, bases, dct):
cls.__instance = None
type.__init__(cls, name, bases, dct)
def __call__(cls, *args, **kw):
if cls.__instance is None:
cls.__instance = type.__call__(cls, *args,**kw)
return cls.__instance
class FreeCADShipSimulation(threading.Thread):
__metaclass__ = Singleton
def __init__ (self, device, endTime, output, FSmesh, waves):
""" Thread constructor.
@param device Device to use.
@param endTime Maximum simulation time.
@param output [Rate,Type] Output rate, Type=0 if FPS, 1 if IPF.
@param FSmesh Free surface mesh faces.
@param waves Waves parameters (A,T,phi,heading)
"""
threading.Thread.__init__(self)
# Setup as stopped
self.active = False
# Build OpenCL context and command queue
self.device = device
if self.device == None: # Can't use OpenCL
self.context = None
self.queue = None
else:
self.context = cl.Context(devices=[self.device])
self.queue = cl.CommandQueue(self.context)
# Storage data
self.endTime = endTime
self.output = output
self.FSmesh = FSmesh
self.waves = waves
def run(self):
""" Runs the simulation.
"""
self.active = True
# Simulation stuff
if self.device == None:
from Sim import initialization
else:
from clSim import initialization
msg = Translator.translate("\t[Sim]: Initializating OpenCL...\n")
FreeCAD.Console.PrintMessage(msg)
init = initialization.perform(self.FSmesh,self.waves,self.context,self.queue)
msg = Translator.translate("\t[Sim]: Iterating (outputs will be noticed)...\n")
FreeCAD.Console.PrintMessage(msg)
while self.active:
print("Im thread, Im running...")
time.sleep(1)
# ...
print("Im thread, step done!")
# Set thread as stopped (and prepare it to restarting)
self.active = False
threading.Event().set()
threading.Thread.__init__(self)
def stop(self):
""" Call to stop execution.
"""
self.active = False
def isRunning(self):
""" Report thread state
@return True if thread is running, False otherwise.
"""
return self.active

View File

@ -0,0 +1,204 @@
#***************************************************************************
#* *
#* 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
# pyOpenCL
import pyopencl as cl
# Module
import SimInstance
from shipUtils import Paths, Translator
from Simulation import FreeCADShipSimulation as Sim
import time
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/simRun/TaskPanel.ui"
self.sim = False
def accept(self):
msg = Translator.translate("Building data...\n")
App.Console.PrintMessage(msg)
# Get GUI data
endTime = self.form.time.value()
output = []
output.append(self.form.output.value())
output.append(self.form.outputType.currentIndex())
devId = self.form.device.currentIndex() - 1 # First is not OpenCL
# Get OpenCL device
device = None
count = 0
platforms = cl.get_platforms()
for p in platforms:
devs = p.get_devices()
for d in devs:
if count == devId:
device = d
count = count + 1
# Get free surfaces data
FSMesh = SimInstance.FSMesh(self.sim)
wData = self.sim.Waves
wDir = self.sim.Waves_Dir
waves = []
for i in range(0,len(wData)):
waves.append([wData[i].x, wData[i].y, wData[i].z, wDir[i]])
msg = Translator.translate("Launching simulation...\n")
App.Console.PrintMessage(msg)
# Build simulation thread
simulator = Sim(device, endTime, output, FSMesh, waves)
simulator.start()
msg = Translator.translate("Done!\n")
App.Console.PrintMessage(msg)
return True
def reject(self):
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.time = form.findChild(QtGui.QDoubleSpinBox, "SimTime")
form.output = form.findChild(QtGui.QDoubleSpinBox, "Output")
form.outputType = form.findChild(QtGui.QComboBox, "OutputType")
form.device = form.findChild(QtGui.QComboBox, "Device")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
# QtCore.QObject.connect(form.time, 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 = Gui.Selection.getSelection()
if not selObjs:
msg = Translator.translate("Ship simulation instance must be selected (no 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("IsShipSimulation")
except ValueError:
continue
if obj.IsShipSimulation:
# Test if another ship already selected
if self.sim:
msg = Translator.translate("More than one ship simulation selected (extra simulations will be neglected)\n")
App.Console.PrintWarning(msg)
break
self.sim = obj
# Test if any valid ship was selected
if not self.sim:
msg = Translator.translate("Ship simulation instance must be selected (no valid simulation found at selected objects)\n")
App.Console.PrintError(msg)
return True
# Get the list of devices
self.form.device.addItem("CPU based version (No OpenCL)")
devices = []
platforms = cl.get_platforms()
for p in platforms:
devs = p.get_devices()
for d in devs:
devices.append([p,d])
dname = d.get_info(cl.device_info.NAME)
pname = p.get_info(cl.platform_info.NAME)
self.form.device.addItem(dname + " (" + pname + ")")
if not len(devices):
msg = Translator.translate("Can't find OpenCL devices\n")
App.Console.PrintWarning(msg)
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("Run the simulation"))
self.form.findChild(QtGui.QLabel, "SimTimeLabel").setText(Translator.translate("Simulation time"))
self.form.findChild(QtGui.QLabel, "OutputLabel").setText(Translator.translate("Output"))
self.form.findChild(QtGui.QLabel, "DeviceLabel").setText(Translator.translate("OpenCL device"))
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel
def stopSimulation():
try:
simulator = Sim()
if not simulator.isRunning():
msg = Translator.translate("Simulation already stopped\n")
App.Console.PrintWarning(msg)
return
except:
msg = Translator.translate("Any active simulation to stop!\n")
App.Console.PrintError(msg)
return
simulator.stop()
msg = Translator.translate("Simulation will stop at the end of actual iteration\n")
App.Console.PrintMessage(msg)

View File

@ -0,0 +1,131 @@
<?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>300</width>
<height>102</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Create new simulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="SimTimeLabel">
<property name="text">
<string>Simulation time</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="SimTime">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>10000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>3600.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="SimTimeUnitsLabel">
<property name="maximumSize">
<size>
<width>16</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>s</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="OutputLabel">
<property name="text">
<string>Output</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="Output">
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="OutputType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>56</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string comment="FPS = Frames per second, IPF = Iterations per frame"/>
</property>
<item>
<property name="text">
<string>FPS</string>
</property>
</item>
<item>
<property name="text">
<string>IPF</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="DeviceLabel">
<property name="text">
<string>OpenCL device</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="Device"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,40 @@
#***************************************************************************
#* *
#* 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()
def stop():
""" Stops the simulation """
TaskPanel.stopSimulation()

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 *
#* *
#***************************************************************************
# FreeCAD
from shipUtils import Paths
# pyOpenCL
import pyopencl as cl
import numpy as np
# Standard
import math
def loadProgram(context, file):
""" Loads a file and comnpile it.
@param context OpenCL context where apply.
@param file File to load and compile.
@return Ready to use OpenCL program.
"""
f = open(file, 'r')
str = "".join(f.readlines())
return cl.Program(context, str).build()
def clPath():
""" Gets the OpenCL kernels path
@return OpenCL kernels path
"""
path = Paths.modulePath() + "/OpenCL"
return path
def globalSize(n):
""" Compute global size from amount of data.
@param n Amount of data.
@return global size.
"""
localSize = 256.0
return int(math.ceil(n/localSize)*localSize)

View File

@ -0,0 +1,24 @@
#***************************************************************************
#* *
#* 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 initialization, Utils

View File

@ -0,0 +1,113 @@
#***************************************************************************
#* *
#* 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 *
#* *
#***************************************************************************
# Simulation stuff
from Utils import *
# pyOpenCL
import pyopencl as cl
import numpy as np
class perform:
def __init__(self, FSmesh, waves, context, queue):
""" Constructor, includes program loading.
@param FSmesh Initial free surface mesh.
@param waves Considered simulation waves (A,T,phi,heading).
@param context OpenCL context where apply.
@param queue OpenCL command queue.
"""
self.context = context
self.queue = queue
self.program = loadProgram(context, clPath() + "/simInit.cl")
self.loadData(FSmesh, waves)
self.execute()
def loadData(self, FSmesh, waves):
""" Convert data to numpy format, and create OpenCL
buffers.
@param FSmesh Initial free surface mesh.
@param waves Considered simulation waves (A,T,phi,heading).
"""
mf = cl.mem_flags
nx = len(FSmesh)
ny = len(FSmesh[0])
nW = len(waves)
# Mesh data
p = np.ndarray((nx*ny, 4), dtype=np.float32)
n = np.ndarray((nx*ny, 4), dtype=np.float32)
a = np.ndarray((nx*ny, 1), dtype=np.float32)
for i in range(0, nx):
for j in range(0, ny):
id = i*ny + j
pos = FSmesh[i][j].pos
normal = FSmesh[i][j].normal
area = FSmesh[i][j].area
p[id,0] = pos.x
p[id,1] = pos.y
p[id,2] = pos.z
p[id,3] = 1.
n[id,0] = normal.x
n[id,1] = normal.y
n[id,2] = normal.z
n[id,3] = 0.
a[id,0] = area
p_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=p)
n_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=n)
a_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=a)
v_cl = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny*4 * np.dtype('float32').itemsize)
f_cl = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny*4 * np.dtype('float32').itemsize)
phi = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny * np.dtype('float32').itemsize)
Phi = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny * np.dtype('float32').itemsize)
self.fs = {'Nx':nx, 'Ny':ny, 'pos':p_cl, 'vel':v_cl, 'acc':f_cl, \
'normal':n_cl, 'area':a_cl, 'velPot':phi, 'accPot':Phi}
# Waves data
w = np.ndarray((nW, 4), dtype=np.float32)
for i in range(0,nW):
w[i,0] = waves[i][0]
w[i,1] = waves[i][1]
w[i,2] = waves[i][2]
w[i,3] = waves[i][3]
w_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=w)
self.waves = {'N':nW, 'data':w_cl}
# Ensure that all data has been written
self.queue.finish()
def execute(self):
""" Compute initial conditions. """
# Global size computation
N = np.ndarray((2, 1), dtype=np.uint32)
N[0] = self.fs['Nx']
N[1] = self.fs['Ny']
n = np.uint32(self.waves['N'])
gSize = (globalSize(N[0]),globalSize(N[1]),)
# Kernel arguments
kernelargs = (self.fs['pos'],
self.fs['vel'],
self.fs['acc'],
self.waves['data'],
self.fs['velPot'],
self.fs['accPot'],
N, n)
# Kernel launch
self.program.FS(self.queue, gSize, None, *(kernelargs))
self.queue.finish()

View File

@ -24,6 +24,7 @@
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
import Part
# Qt library
from PyQt4 import QtGui,QtCore
# Module

View File

@ -24,8 +24,8 @@
import os
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base
from FreeCAD import Image, ImageGui
from FreeCAD import Base, Image, ImageGui
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator

View File

@ -24,7 +24,7 @@
# FreeCAD modules
import FreeCAD,FreeCADGui
from FreeCAD import Base
from FreeCAD import Part
import Part
# FreeCADShip modules
from shipUtils import Paths, Translator