From 48c69c820ca6ea47216a2b657895c9322acd60df Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 8 Apr 2013 12:54:46 +0200 Subject: [PATCH 01/53] Implement GeometryCurvePy::length --- src/Mod/Part/App/GeometryCurvePy.xml | 6 ++++++ src/Mod/Part/App/GeometryCurvePyImp.cpp | 26 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/Mod/Part/App/GeometryCurvePy.xml b/src/Mod/Part/App/GeometryCurvePy.xml index 78090909c6..e4308eb72d 100644 --- a/src/Mod/Part/App/GeometryCurvePy.xml +++ b/src/Mod/Part/App/GeometryCurvePy.xml @@ -26,6 +26,12 @@ Discretizes the curve using a given deflection or number of points and returns a list of points + + + Computes the length of a curve +length([uMin,uMax,Tol]) -> Float + + Computes the point of parameter u on this curve diff --git a/src/Mod/Part/App/GeometryCurvePyImp.cpp b/src/Mod/Part/App/GeometryCurvePyImp.cpp index 01f91500a1..78d3efcf29 100644 --- a/src/Mod/Part/App/GeometryCurvePyImp.cpp +++ b/src/Mod/Part/App/GeometryCurvePyImp.cpp @@ -28,6 +28,7 @@ # include # include # include +# include # include # include # include @@ -156,6 +157,31 @@ PyObject* GeometryCurvePy::discretize(PyObject *args) return 0; } +PyObject* GeometryCurvePy::length(PyObject *args) +{ + Handle_Geom_Geometry g = getGeometryPtr()->handle(); + Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(g); + try { + if (!c.IsNull()) { + double u=c->FirstParameter(); + double v=c->LastParameter(); + double t=Precision::Confusion(); + if (!PyArg_ParseTuple(args, "|ddd", &u,&v,&t)) + return 0; + double len = GCPnts_AbscissaPoint::Length(GeomAdaptor_Curve(c),u,v,t); + return PyFloat_FromDouble(len); + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PyExc_Exception, e->GetMessageString()); + return 0; + } + + PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + return 0; +} + PyObject* GeometryCurvePy::value(PyObject *args) { Handle_Geom_Geometry g = getGeometryPtr()->handle(); From 8d77f551046f5939d7a623bafd7322f30d9c8d53 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 8 Apr 2013 17:03:41 -0300 Subject: [PATCH 02/53] 0001068: Bug in Draft DXF export --- src/Mod/Draft/DraftGeomUtils.py | 17 ++++++++++++++++- src/Mod/Draft/importDXF.py | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index c5fb3e9a0c..f378baf267 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -419,7 +419,7 @@ def mirror (point, edge): else: return None -def isClockwise(edge): +def isClockwise(edge,ref=None): """Returns True if a circle-based edge has a clockwise direction""" if not geomType(edge) == "Circle": return True @@ -429,11 +429,26 @@ def isClockwise(edge): # we take an arbitrary other point on the edge that has little chances to be aligned with the first one... v2 = edge.Curve.tangent(edge.ParameterRange[0]+0.01)[0] n = edge.Curve.Axis + # if that axis points "the wrong way" from the reference, we invert it + if not ref: + ref = Vector(0,0,1) + if n.getAngle(ref) > math.pi/2: + n = DraftVecUtils.neg(n) if DraftVecUtils.angle(v1,v2,n) < 0: return False if n.z < 0: return False return True + +def isWideAngle(edge): + """returns True if the given edge is an arc with angle > 180 degrees""" + if geomType(edge) != "Circle": + return False + r = edge.Curve.Radius + total = 2*r*math.pi + if edge.Length > total/2: + return True + return False def findClosest(basepoint,pointslist): ''' diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 1a9a34865e..0cb2656ebb 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1255,6 +1255,8 @@ def getWire(wire,nospline=False): v2 = edge.Vertexes[-1].Point c = edge.Curve.Center angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c))) + if DraftGeomUtils.isWideAngle(edge): + angle = math.pi*2 - angle # if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))): # angle = -angle # polyline bulge -> negative makes the arc go clockwise From 52b0c605d46defbb8dcf97fa38a66f78164597b6 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 8 Apr 2013 17:09:31 -0300 Subject: [PATCH 03/53] 0001062: New Part Helix icon --- .../Resources/icons/Part_Helix_Parametric.svg | 332 +++++++----------- 1 file changed, 132 insertions(+), 200 deletions(-) diff --git a/src/Mod/Part/Gui/Resources/icons/Part_Helix_Parametric.svg b/src/Mod/Part/Gui/Resources/icons/Part_Helix_Parametric.svg index 342f2cc42a..686202f6bc 100644 --- a/src/Mod/Part/Gui/Resources/icons/Part_Helix_Parametric.svg +++ b/src/Mod/Part/Gui/Resources/icons/Part_Helix_Parametric.svg @@ -1,230 +1,162 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + sodipodi:docname="Part_Helix_Parametric_experimental4.svg"> + id="metadata2211"> image/svg+xml - + + + + + + + id="g2193" + style="fill:none;stroke:#0034ff;stroke-width:1.82898951;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + transform="matrix(-1.0637318,-1.8704763,1.9125674,-1.0403216,-139.48663,1580.7514)"> - - - + style="stroke:#0034ff;stroke-width:1.82898951;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 593.517,408.676 -0.203,0.018 -0.221,0.062 -0.486,0.249 -0.525,0.399 -0.413,0.388 -0.42,0.451 -0.838,1.056 -0.81,1.213 -0.763,1.325 -0.828,1.681 -0.725,1.76 -0.601,1.806 -0.259,0.958 -0.215,0.955 -0.15,0.849 -0.106,0.836 -0.053,0.699 -0.015,0.681 0.044,0.871 0.124,0.815 0.212,0.739 0.162,0.38 0.193,0.345 0.304,0.4 0.358,0.324 0.407,0.242 0.417,0.147" + id="path2197" + inkscape:connector-curvature="0" + style="stroke:#0034ff;stroke-width:1.82898951;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 588.107,428.325 0.536,0.078 0.572,-0.024 0.598,-0.118 0.46,-0.147 0.467,-0.192 0.618,-0.314 0.619,-0.378 0.626,-0.442 0.62,-0.492 1.193,-1.096 1.133,-1.223 1.021,-1.262 0.947,-1.325 0.862,-1.366 0.766,-1.384 0.71,-1.514 0.321,-0.811 0.264,-0.785 0.17,-0.617 0.121,-0.58 0.081,-0.771 -0.008,-0.336 -0.042,-0.295 -0.078,-0.25 -0.113,-0.198 -0.217,-0.184 -0.28,-0.068" + id="path2199" + inkscape:connector-curvature="0" + style="stroke:#0034ff;stroke-width:1.82898951;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 600.074,412.231 -0.203,0.017 -0.221,0.062 -0.486,0.25 -0.525,0.399 -0.413,0.388 -0.42,0.451 -0.838,1.056 -0.81,1.213 -0.763,1.325 -0.828,1.681 -0.725,1.76 -0.601,1.805 -0.259,0.958 -0.215,0.955 -0.15,0.849 -0.106,0.837 -0.053,0.698 -0.015,0.681 0.044,0.872 0.124,0.814 0.212,0.74 0.162,0.38 0.193,0.345 0.304,0.4 0.358,0.324 0.407,0.241 0.416,0.147" + id="path2201" + inkscape:connector-curvature="0" + style="stroke:#0034ff;stroke-width:1.82898951;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + + + + + + + + + From 81e05c571386517e404c55867212c6a53f113dbc Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 8 Apr 2013 23:53:44 -0300 Subject: [PATCH 04/53] Small cleanup in sphinx docs --- src/Doc/sphinx/Document.rst | 8 + src/Doc/sphinx/Draft.rst | 20 +- src/Doc/sphinx/DraftGeomUtils.rst | 10 + src/Doc/sphinx/DraftSnap.rst | 10 + src/Doc/sphinx/DraftTrackers.rst | 10 + src/Doc/sphinx/DraftVecUtils.rst | 10 + src/Doc/sphinx/_static/freecad.css | 596 ++++------------------- src/Doc/sphinx/_templates/searchbox.html | 2 +- src/Doc/sphinx/conf.py | 7 +- src/Doc/sphinx/index.rst | 8 +- 10 files changed, 146 insertions(+), 535 deletions(-) create mode 100644 src/Doc/sphinx/Document.rst create mode 100644 src/Doc/sphinx/DraftGeomUtils.rst create mode 100644 src/Doc/sphinx/DraftSnap.rst create mode 100644 src/Doc/sphinx/DraftTrackers.rst create mode 100644 src/Doc/sphinx/DraftVecUtils.rst diff --git a/src/Doc/sphinx/Document.rst b/src/Doc/sphinx/Document.rst new file mode 100644 index 0000000000..3e82c8379e --- /dev/null +++ b/src/Doc/sphinx/Document.rst @@ -0,0 +1,8 @@ +The FreeCAD Document +==================== + +.. toctree:: + :maxdepth: 4 + +.. automodule:: ActiveDocument + :members: diff --git a/src/Doc/sphinx/Draft.rst b/src/Doc/sphinx/Draft.rst index 4479028b14..3ffaa5ec30 100644 --- a/src/Doc/sphinx/Draft.rst +++ b/src/Doc/sphinx/Draft.rst @@ -1,5 +1,5 @@ -The Draft module -================ +Draft module +============ The Draft module offer several convenient functions to work with simple objects. @@ -8,19 +8,3 @@ The Draft module offer several convenient functions to work with simple objects. .. automodule:: Draft :members: - -.. automodule:: DraftSnap - :members: - -The Draft module also contains two submodules, widely used throughout the Draft and Arch modules: DraftVecUtils, which contains useful methods for dealing with vectors, and DraftGeomUtils, which offers many tools for working with OpenCascade geometry. - -.. automodule:: DraftVecUtils - :members: - -.. automodule:: DraftGeomUtils - :members: - -The Draft module also features a module that contains trackers, special objects made to display 3D temporary geometry in the 3D scene, that have no real existence in the FreeCAD document. - -.. automodule:: DraftTrackers - :members: diff --git a/src/Doc/sphinx/DraftGeomUtils.rst b/src/Doc/sphinx/DraftGeomUtils.rst new file mode 100644 index 0000000000..8875a57d35 --- /dev/null +++ b/src/Doc/sphinx/DraftGeomUtils.rst @@ -0,0 +1,10 @@ +Draft Geometry Utilities +======================== + +The DraftGeomUtils module offer tools to manipulate Part geometry. + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DraftGeomUtils + :members: diff --git a/src/Doc/sphinx/DraftSnap.rst b/src/Doc/sphinx/DraftSnap.rst new file mode 100644 index 0000000000..ca9089b9da --- /dev/null +++ b/src/Doc/sphinx/DraftSnap.rst @@ -0,0 +1,10 @@ +Draft Snapper +============= + +The Draft Snapper manages object snapping in Draft and Arch modules. + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DraftSnap + :members: diff --git a/src/Doc/sphinx/DraftTrackers.rst b/src/Doc/sphinx/DraftTrackers.rst new file mode 100644 index 0000000000..6a0ada8c25 --- /dev/null +++ b/src/Doc/sphinx/DraftTrackers.rst @@ -0,0 +1,10 @@ +Draft Trackers +============== + +Different trackers (temporary screen widgets) used in the Draft and Arch modules. + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DraftTrackers + :members: diff --git a/src/Doc/sphinx/DraftVecUtils.rst b/src/Doc/sphinx/DraftVecUtils.rst new file mode 100644 index 0000000000..dbf44d7818 --- /dev/null +++ b/src/Doc/sphinx/DraftVecUtils.rst @@ -0,0 +1,10 @@ +Draft Vector Utilities +====================== + +The DraftVecUtils module offer several convenient utilities to deal with vectors + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DraftVecUtils + :members: diff --git a/src/Doc/sphinx/_static/freecad.css b/src/Doc/sphinx/_static/freecad.css index e596ecb357..4f78bb38ed 100644 --- a/src/Doc/sphinx/_static/freecad.css +++ b/src/Doc/sphinx/_static/freecad.css @@ -1,526 +1,100 @@ -/* FreeCAD CSS template by Yorik */ - -/* general settings ******************************* */ - -a, #bodyContent a.external { - color: #0092E8; - } - -a.new, .new a, #p-cactions .new a, #p-personal a.new { - color: #FF1F00; - } - -h1 { - background: #0092E8; - border: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - color: white; - font-weight: bold; - padding: 5px; - margin: 10px 0; - } - -h2 { - font-weight: normal; - } - -h4 { - font-size: 90%; - font-weight: bold; - } - -pre { - border: 1px solid #AAAAAA; - background: #EEEEEE; - } - -.docnav { - background: #D3D7D9; - padding: 3px; - border: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - margin-top: 15px; - } - -.languages { - font-size: 9px; - padding:2px 5px; - color: #666666; - border: none; - border-top: 1px solid #666666; - margin-top: 10px; - } - -#bodyContent a[href^="https://"], .link-https { - padding: 0 16px 0 0; - } - -/* homepage ******************************* */ - -body[class*='page-Main_Page'] { - text-align: justify; - } - -body[class*='page-Main_Page'] h1 { - background: none; - margin-bottom: 0; - border-bottom: 1px solid #638C9C; - padding-bottom: 15px; - } - -body[class*='page-Main_Page'] h2 { - color: #FFF; - border-bottom: none; - margin-bottom: 20px !important; - } - -body[class*='page-Main_Page'] h3 { - color: white; - font-size: 105%; - font-weight: bold; - } - -body[class*='page-Main_Page'] h1 .mw-headline { - font-size: 2em; - letter-spacing: 20px; - } - -body[class*='page-Main_Page'] #bodyContent a:visited { - color: #0092E8; - } - -body[class*='page-Main_Page'] h1.firstHeading { - display:none; - } - -body[class*='page-Main_Page'] #content { - background: transparent; - color: white; - } - -body[class*='page-Main_Page'] #content ul { - list-style-type: none; - list-style-image: none; - margin: 0; - } - -/* homepage toolboxes & menus ******************************** */ - -.main-toolbox { - float: right; - width: 300px; - margin-left: 25px; - } - -.main-menu { - margin-bottom: 40px; - } - -.main-menu a { - color: #FFF !important; - } - -.main-content { - display: table; - } - -#feedholder, #mantisholder, .sidebox, #fbholder { - max-width: 300px; - border: 1px solid #AAAAAA; - background-color:#EEEEEE; - padding:1.2em; - color: black; - margin-top: 10px; - font-size: 0.85em; - text-align: left; - } - -#feedholder .title, #mantisholder .title, .sidebox .title { - font-weight: bold; - font-size: 1.2em; - } - -#feedholder .title a, #mantisholder .title a, .sidebox .title a { - float: right; - } - -#fbholder { - padding: 0; - } - -.downloadbox { - background: white url(/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/6/65/Download.jpg) top left no-repeat; - padding: 10px 10px 10px 80px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - text-align: left; - margin-bottom: 15px; - color: black; - font-weight: bold; - } - -#bodyContent .downloadbox li a.external { - display: box; - color: #005295; - padding: 3px 13px 3px 3px; - } - -/* wikibars ******************************** */ - -#p-cactions { - padding: 0 60px; - /* top: 3px; */ - width: auto; - z-index: 2; - } - -#p-cactions li, #p-cactions li a, #p-personal li a { - color: #0092E8; - background: none; - padding: 1px 5px !important; - margin: 0 !important; - } - -#globalWrapper { - background: #171a2a url(/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/1/1f/Background.jpg) top left no-repeat !important; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - width: auto !important; - margin:5px; - } - -.portlet { - width: auto; - padding-right: 5px; - } - -.pBody { - background: transparent; - border: none; - padding: 0 } - -.pBody a { - color: white; - padding: 1px 5px !important; - } - -.portlet ul { - margin: 0; - } - -.portlet li { - margin-left: 5px; - list-style-position: inside; - } - -#column-one { - margin-left: 3px; - padding-top: 160px; - } - -#p-cactions li a:hover, #p-personal li a:hover, #p-cactions li.selected a, #bodyContent .downloadbox li a.external:hover { - color: white; - background: #0092E8; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - text-decoration: none; - } - -/* content ******************************** */ - -#column-content { - margin:0 0 0.6em -12.2em !important; - padding: 5px; - width: 96%; - } - -#content { - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - } - -#content, #p-cactions li { - border: none; - padding: 0.6em 1em 1em; - } - -#footer { - background: none; - border: none; - color: #fff; - } - -/* sidebar ******************************** */ - -.portlet h5 { - color: #638C9C; - text-transform: uppercase; - font-size: 75%; - height: 15px; - display: block; - margin-bottom: 5px; - border-bottom: 1px solid #638C9C; - padding-left: 10px; - } - -#p- h5 { - display: none; - } - -#p-search, #p-Documentation, #p-tb, #p-languages, #p-Meta, #p-Feedback, #p-Manual { - max-width: 180px; - } - -#n-Basic, #n-Advanced, #n-Development, #n-Using-FreeCAD, #n-Python-Scripting { - list-style: none; - font-size: 12px; - text-transform: uppercase; - font-weight: bold; - padding: 3px 0; - } - -#n-Home { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/9/9a/Home.png); - } - -#n-Features { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/5/53/Features16.png); - } - -#n-Screenshots { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/e/ef/Screenshots16.png); - } - -#n-Downloads { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/e/ed/Download16.png); - } - -#n-Getting-Started { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/b/b4/Gettingstarted16.png); - } - -#n-FAQ { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/8/86/Faq16.png); - } - -#n-Forum { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/6/6a/Forum16.png); - } - -#n-Tutorials { - list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/4/46/Tutorials.png); - } - -/* Commands Template******************* */ - -.ct { - padding: 5px; - background: #eeeeee; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - margin: 5px 0 15px 8px; - } - -.ctEven { - background-color:#F9F9F9; - border:1px solid #AAAAAA; - padding: 2px; - } - -.ctToc .toc { - width: 100%; - } - -.left { - text-align: left; - } - -/* API ******************************** */ - -.api { - margin-left: 30px; - } - -.api .function, dl dt { - padding: 3px 2px 3px 20px; - border-radius: 3px; - } - -dl.class dt { - background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/0/0f/Class.png") left center no-repeat; - } - -dl.function dt, dl.method dt { - background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/2/20/Method.png") left center no-repeat; - } - -dl.attribute dt { - background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/4/47/Property.png") left center no-repeat; - } - -dl dt tt { - font-weight: bold; - } - -dl dt big { - margin: 0 3px 0 3px; - font-size: 0.8em; - } - -.api .description { - padding-left: 30px; - } - -.highlight { - background: #ffffff !important; - margin-bottom: 40px; - } - -.highlight pre { - margin-left: 30px; - padding: 5px; - } - -/* Screenshots ************************ */ - -.screenthumbs { - padding: 5px; - background: #eeeeee; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - width: 800px; - } - -/* Translations *********************** */ - -body[class*='_it'] h1.firstHeading, body[class*='_fr'] h1.firstHeading { - display:none; - } - -h1 .editsection a:link { - color: white; - font-weight: normal; - } - -/* Charts *********************** */ - -.orgchart { - margin: 10px; - background: #EEEEEE; - text-align: center; - width: 800px; - padding: 4px; - border-radius: 5px; - border-spacing: 0; - } - -.orgheader { - background: #9FBDE0; - } - -.orgchart td { - padding: 0; - } -/* Printing ************************ */ - -@media print { +/* FreeCAD sphinx CSS file */ body { - font: small sans-serif; - text-align: left; - } - -a{ - color: blue; - } - -h1 { - background: none; - border: none; - color: black; - font-weight: bold; - padding: 5px; - margin-top: 10px; - } - -#globalWrapper { - backgound: none; - } - -#column-content { - margin:0 !important; - padding: 5px; - width: auto; - } - -.docnav, .languages, #sf_header { - display: none; - } - -.toc { - border: none; - } - -.thumbcaption { - text-align: left; - } - + background: #191b26; + background-attachment: fixed; + background-size: cover; + font-family: Arial, Helvetica, sans-serif; + color: #eee; + opacity: 0.9; + text-align: justify; + /* font-size: 0.9em; */ } -/* sphinx-specific *****************************/ - -body { - background: #171a2a url(http://www.sourceforge.net/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/1/1f/Background.jpg) top left no-repeat !important; - font-family: sans-serif; - color: #ffffff; +a { + font-weight: bold; + text-decoration: none; + color: #0F3472; } -.document { - background: url(http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/7/70/MediaWikiSidebarLogo.png) top left no-repeat; +a img { + border: 0; } -.related h3 { - display: none; -} - -.related ul { - float: right; -} - -.related ul li { - display: inline; - font-size: 0.8em; -} - -.documentwrapper { - color: #000000; - background: none repeat scroll 0 0 white; - border-radius: 5px; - padding: 0.6em; - position: relative; - z-index: 2; - float: right; - width: 75% -} - -.sphinxsidebar { - font-size: 0.8em; - width: 220px; - padding-top: 100px; -} - -.clearer { - clear: both; +a:hover { + text-decoration: underline; } a.headerlink { display: none; } -.footer { - clear: both; - font-size: 0.7em; - text-align: center; +h1 { + font-size: 24px; + font-weight: bold; + margin: 0; + background: url("/images/freecad.png") top left no-repeat; + color: #000; + padding-left: 40px; + border-bottom: 1px solid #444; } + +h2 { + font-size: 18px; + margin: 30px 0 0 0; +} + +.document { + background-color: #eee; + display: table; + width: 960px; + box-shadow: 0 0 5px #000; + padding: 10px; + margin: auto; + color: #000; +} + +.related { + margin: auto; + width: 960px; +} + +.related a { + color: #1E90FF; + font-size: 0.9em; +} + +.related h3 { + display: none; +} + +.related li { + display: inline; +} + +.footer { + margin: auto; + width: 960px; +} + +.descname { + font-weight: bold; +} + +.function, .attribute, .method { + border-bottom: 1px solid #bbb; + padding: 10px; +} + +@media print { + +.document { + box-shadow: none; +} + +.related { + display: none; +} + +} + diff --git a/src/Doc/sphinx/_templates/searchbox.html b/src/Doc/sphinx/_templates/searchbox.html index 0c41389fcd..b4be3686f0 100644 --- a/src/Doc/sphinx/_templates/searchbox.html +++ b/src/Doc/sphinx/_templates/searchbox.html @@ -20,7 +20,7 @@ {{ _('Enter search terms or a module, class or function name.') }}

- Go back to the FreeCAD wiki + Go back to the FreeCAD homepage

diff --git a/src/Doc/sphinx/conf.py b/src/Doc/sphinx/conf.py index 512f6f5fc0..77e697346e 100644 --- a/src/Doc/sphinx/conf.py +++ b/src/Doc/sphinx/conf.py @@ -55,6 +55,7 @@ elif commands.getstatusoutput("locate FreeCAD/lib")[0] == 0: import FreeCAD, FreeCADGui FreeCADGui.showMainWindow() # this is needed for complete import of GUI modules +from FreeCAD import Document # -- General configuration ----------------------------------------------------- @@ -86,9 +87,9 @@ copyright = u'2011, Jürgen Riegel, Werner Mayer, Yorik van Havre' # built documents. # # The short X.Y version. -version = '0.12' +version = '0.13' # The full version, including alpha/beta/rc tags. -release = '0.12' +release = '0.13' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -155,7 +156,7 @@ html_title = "FreeCAD API documentation" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/src/Doc/sphinx/index.rst b/src/Doc/sphinx/index.rst index bcb2a9599d..c4004f32ef 100644 --- a/src/Doc/sphinx/index.rst +++ b/src/Doc/sphinx/index.rst @@ -13,11 +13,16 @@ This is the complete python API reference of the FreeCAD appication FreeCAD.rst FreeCADGui.rst + Document.rst Mesh.rst Part.rst Sketch.rst PartDesign.rst Draft.rst + DraftVecUtils.rst + DraftGeomUtils.rst + DraftTrackers.rst + DraftSnap.rst Arch.rst Drawing.rst RayTracing.rst @@ -25,5 +30,4 @@ This is the complete python API reference of the FreeCAD appication * :ref:`genindex` * :ref:`modindex` * :ref:`search` - -* `Go back to the FreeCAD wiki `_ +* `FreeCAD homepage `_ From 69f7a1419378cc011c3ec4721e6457e990910de9 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 9 Apr 2013 19:43:45 -0300 Subject: [PATCH 05/53] 0001035: WebGL exporter The Arch module now features a webgl exporter that produces an all-included HTML file that displays the exported objects in WebGL-capable web browsers. Many enhancements are still necessary, especially with lights and materials. At time of export, the exporter downloads the three.js library from github and includes it in the HTML file, so it has no other dependencies. --- src/Mod/Arch/CMakeLists.txt | 1 + src/Mod/Arch/InitGui.py | 1 + src/Mod/Arch/importWebGL.py | 166 +++++++++++++++++++++++++++++++ src/Mod/Draft/Draft.py | 26 ++--- src/WindowsInstaller/ModArch.wxi | 2 +- 5 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 src/Mod/Arch/importWebGL.py diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt index fcfd728bb8..28f691455e 100644 --- a/src/Mod/Arch/CMakeLists.txt +++ b/src/Mod/Arch/CMakeLists.txt @@ -21,6 +21,7 @@ SET(Arch_SRCS ArchAxis.py ArchVRM.py ArchRoof.py + importWebGL.py ) SOURCE_GROUP("" FILES ${Arch_SRCS}) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index ddba892dcc..1f5f2386d3 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -129,6 +129,7 @@ class ArchWorkbench(Workbench): FreeCADGui.addWorkbench(ArchWorkbench) FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") +FreeCAD.addExportType("WebGL file (*.html)","importWebGL") # check for pycollada try: import collada diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py new file mode 100644 index 0000000000..a8a8c4a2c9 --- /dev/null +++ b/src/Mod/Arch/importWebGL.py @@ -0,0 +1,166 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2013 * +#* Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Arch,Draft +from DraftTools import translate + +tab = " " + +if open.__module__ == '__builtin__': + pythonopen = open + +def export(exportList,filename): + "exports the given objects to a .html file" + + # get three.min.js + threejspath = Arch.download("https://raw.github.com/mrdoob/three.js/master/build/three.min.js") + threejsfile = pythonopen(threejspath,"r") + threeminjs = threejsfile.read() + threejsfile.close() + + # get objects data + objectsData = '' + for obj in exportList: + objectsData += getObjectData(obj) + + # build the final file + template = getTemplate() + template = template.replace("$ThreeMinJs",threeminjs) + template = template.replace("$CameraData",getCameraData()) + template = template.replace("$ObjectsData",objectsData) + template = template.replace("$TestData",getTestData()) + outfile = pythonopen(filename,"wb") + outfile.write(template) + outfile.close() + FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename) + +def getCameraData(): + "returns the position and direction of the camera as three.js snippet" + + # getting camera position + pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base + #result = "camera.position.set( -10,5,15" # test position + result = "camera.position.set( " + result += str(pos.x) + ", " + result += str(pos.y) + ", " + result += str(pos.z) + + # getting camera lookat vector + lookat = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + lookat = pos.add(lookat) + result += " );\n"+tab+"camera.lookAt( scene.position );\n"+tab + #result += " );\n"+tab+"camera.lookAt( " + #result += str(lookat.x) + ", " + #result += str(lookat.y) + ", " + #result += str(lookat.z) + #result += " );\n"+tab + + # print result + return result + +def getObjectData(obj): + "returns the geometry data of an object as three.js snippet" + + if obj.isDerivedFrom("Part::Feature"): + fcmesh = obj.Shape.tessellate(0.1) + result = "var geom = new THREE.Geometry();\n" + + # adding vertices data + for i in range(len(fcmesh[0])): + v = fcmesh[0][i] + result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n" + result += tab+"console.log(geom.vertices)\n" + for i in range(len(fcmesh[0])): + result += tab+"geom.vertices.push(v"+str(i)+");\n" + + # adding facets data + for f in fcmesh[1]: + result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n" + + # adding material + col = obj.ViewObject.ShapeColor + rgb = Draft.getrgb(col,testbw=False) + #rgb = "#888888" # test color + result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + + # adding the mesh to the scene + result += tab+"var mesh = new THREE.Mesh( geom, material );\n" + result += tab+"scene.add( mesh );\n"+tab + + # print result + return result + +def getTestData(): + "returns a simple cube as three.js snippet" + + #return """var geometry = new THREE.CubeGeometry( .5, .5, .5 ); + # var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } ); + # var mesh = new THREE.Mesh( geometry, material ); + # scene.add( mesh );""" + + return "" + +def getTemplate(): + "returns a html template" + + result = """ + + + FreeCAD model + + + + + + """ + + return result + diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8a30efe501..8d2a39a973 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1283,18 +1283,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct return "0.02,0.02" return "none" - def getrgb(color): - "getRGB(color): returns a rgb value #000000 from a freecad color" - r = str(hex(int(color[0]*255)))[2:].zfill(2) - g = str(hex(int(color[1]*255)))[2:].zfill(2) - b = str(hex(int(color[2]*255)))[2:].zfill(2) - col = "#"+r+g+b - if col == "#ffffff": - print getParam('SvgLinesBlack') - if getParam('SvgLinesBlack'): - col = "#000000" - return col - def getProj(vec): if not plane: return vec nx = DraftVecUtils.project(vec,plane.u) @@ -1520,6 +1508,20 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct else: svg = getCircle(obj.Shape.Edges[0]) return svg + +def getrgb(color,testbw=True): + """getRGB(color,[testbw]): returns a rgb value #000000 from a freecad color + if testwb = True (default), pure white will be converted into pure black""" + r = str(hex(int(color[0]*255)))[2:].zfill(2) + g = str(hex(int(color[1]*255)))[2:].zfill(2) + b = str(hex(int(color[2]*255)))[2:].zfill(2) + col = "#"+r+g+b + if testbw: + if col == "#ffffff": + #print getParam('SvgLinesBlack') + if getParam('SvgLinesBlack'): + col = "#000000" + return col def makeDrawingView(obj,page,lwmod=None,tmod=None): ''' diff --git a/src/WindowsInstaller/ModArch.wxi b/src/WindowsInstaller/ModArch.wxi index f8bdd05c8b..d43d16aef6 100644 --- a/src/WindowsInstaller/ModArch.wxi +++ b/src/WindowsInstaller/ModArch.wxi @@ -32,7 +32,6 @@ - @@ -46,6 +45,7 @@ + From 2255bdd30b4ea8c68a928652c0437ac15d8a2ca6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 10 Apr 2013 09:41:44 +0200 Subject: [PATCH 06/53] Fix build failure --- src/Mod/Part/App/GeometryCurvePyImp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/GeometryCurvePyImp.cpp b/src/Mod/Part/App/GeometryCurvePyImp.cpp index 78d3efcf29..45b35f1daf 100644 --- a/src/Mod/Part/App/GeometryCurvePyImp.cpp +++ b/src/Mod/Part/App/GeometryCurvePyImp.cpp @@ -168,7 +168,8 @@ PyObject* GeometryCurvePy::length(PyObject *args) double t=Precision::Confusion(); if (!PyArg_ParseTuple(args, "|ddd", &u,&v,&t)) return 0; - double len = GCPnts_AbscissaPoint::Length(GeomAdaptor_Curve(c),u,v,t); + GeomAdaptor_Curve adapt(c); + double len = GCPnts_AbscissaPoint::Length(adapt,u,v,t); return PyFloat_FromDouble(len); } } From bbfa8bd40b2105ca5156b9e256c51ca364acca08 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 10 Apr 2013 13:57:44 +0200 Subject: [PATCH 07/53] Do not override edit cursor with pre-selection --- src/Gui/MDIView.cpp | 8 +++++ src/Gui/MDIView.h | 3 ++ src/Gui/Selection.cpp | 57 ++++++++++++++------------------- src/Gui/SplitView3DInventor.cpp | 2 +- src/Gui/SplitView3DInventor.h | 2 +- src/Gui/View3DInventor.cpp | 6 ++-- src/Gui/View3DInventor.h | 4 +-- src/Mod/Mesh/Gui/Command.cpp | 2 +- 8 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/Gui/MDIView.cpp b/src/Gui/MDIView.cpp index c47e628f80..895d4ec4e0 100644 --- a/src/Gui/MDIView.cpp +++ b/src/Gui/MDIView.cpp @@ -85,6 +85,14 @@ void MDIView::deleteSelf() delete this; } +void MDIView::setOverrideCursor(const QCursor& c) +{ +} + +void MDIView::restoreOverrideCursor() +{ +} + void MDIView::onRelabel(Gui::Document *pDoc) { if (!bIsPassive) { diff --git a/src/Gui/MDIView.h b/src/Gui/MDIView.h index e96f7e172c..3a787b5fa5 100644 --- a/src/Gui/MDIView.h +++ b/src/Gui/MDIView.h @@ -77,7 +77,10 @@ public: /** @name Printing */ //@{ public Q_SLOTS: + virtual void setOverrideCursor(const QCursor&); + virtual void restoreOverrideCursor(); virtual void print(QPrinter* printer); + public: /** Print content of view */ virtual void print(); diff --git a/src/Gui/Selection.cpp b/src/Gui/Selection.cpp index ad67904fd1..a42da3a64f 100644 --- a/src/Gui/Selection.cpp +++ b/src/Gui/Selection.cpp @@ -465,32 +465,30 @@ bool SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectN if (DocName != "") rmvPreselect(); - if(ActiveGate) - { + if (ActiveGate) { App::Document* pDoc = getDocument(pDocName); - if (pDoc) { - if(pObjectName){ + if (pObjectName) { App::DocumentObject* pObject = pDoc->getObject(pObjectName); - if(! ActiveGate->allow(pDoc,pObject,pSubName)){ + if (!ActiveGate->allow(pDoc,pObject,pSubName)) { snprintf(buf,512,"Not allowed: %s.%s.%s ",pDocName ,pObjectName ,pSubName ); - if (getMainWindow()){ + if (getMainWindow()) { getMainWindow()->showMessage(QString::fromAscii(buf),3000); Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { - static_cast(mdi)->setCursor(Qt::ForbiddenCursor); - } + mdi->setOverrideCursor(QCursor(Qt::ForbiddenCursor)); } return false; } - }else + } + else return ActiveGate->allow(pDoc,0,0); - }else + } + else return false; } @@ -520,13 +518,13 @@ bool SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectN ,Chng.pSubName ,x,y,z); - if (getMainWindow()){ - getMainWindow()->showMessage(QString::fromAscii(buf),3000); - Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { - static_cast(mdi)->setCursor(Qt::ArrowCursor); - } - } + //FIXME: We shouldn't replace the possibly defined edit cursor + //with the arrow cursor. But it seems that we don't even have to. + //if (getMainWindow()){ + // getMainWindow()->showMessage(QString::fromAscii(buf),3000); + // Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); + // mdi->restoreOverrideCursor(); + //} Notify(Chng); signalSelectionChanged(Chng); @@ -587,11 +585,9 @@ void SelectionSingleton::rmvPreselect() hy = 0; hz = 0; - if (getMainWindow()){ + if (ActiveGate && getMainWindow()) { Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { - static_cast(mdi)->setCursor(Qt::ArrowCursor); - } + mdi->restoreOverrideCursor(); } //Base::Console().Log("Sel : Rmv preselect \n"); @@ -605,7 +601,7 @@ const SelectionChanges &SelectionSingleton::getPreselection(void) const // add a SelectionGate to control what is selectable void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate) { - if(ActiveGate) + if (ActiveGate) rmvSelectionGate(); ActiveGate = gate; @@ -621,9 +617,7 @@ void SelectionSingleton::rmvSelectionGate(void) Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { Gui::MDIView* mdi = doc->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { - static_cast(mdi)->setCursor(Qt::ArrowCursor); - } + mdi->restoreOverrideCursor(); } } } @@ -654,15 +648,12 @@ bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectN temp.pObject = 0; // check for a Selection Gate - if(ActiveGate) - { - if(! ActiveGate->allow(temp.pDoc,temp.pObject,pSubName)){ - if (getMainWindow()){ + if (ActiveGate) { + if (!ActiveGate->allow(temp.pDoc,temp.pObject,pSubName)) { + if (getMainWindow()) { getMainWindow()->showMessage(QString::fromAscii("Selection not allowed by filter"),5000); Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { - static_cast(mdi)->setCursor(Qt::ForbiddenCursor); - } + mdi->setOverrideCursor(Qt::ForbiddenCursor); } QApplication::beep(); return false; diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index 5ea8d3fa0f..102cb781e1 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -354,7 +354,7 @@ bool AbstractSplitView::onHasMsg(const char* pMsg) const return false; } -void AbstractSplitView::setCursor(const QCursor& aCursor) +void AbstractSplitView::setOverrideCursor(const QCursor& aCursor) { //_viewer->getWidget()->setCursor(aCursor); } diff --git a/src/Gui/SplitView3DInventor.h b/src/Gui/SplitView3DInventor.h index de7254ec49..2131f93a12 100644 --- a/src/Gui/SplitView3DInventor.h +++ b/src/Gui/SplitView3DInventor.h @@ -54,7 +54,7 @@ public: View3DInventorViewer *getViewer(unsigned int) const; - void setCursor(const QCursor&); + void setOverrideCursor(const QCursor&); protected: void setupSettings(); diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 6c9c207f48..1b2b934ca7 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -789,14 +789,14 @@ void View3DInventor::removeOverlayWidget() if (overlay) stack->removeWidget(overlay); } -void View3DInventor::setCursor(const QCursor& aCursor) +void View3DInventor::setOverrideCursor(const QCursor& aCursor) { _viewer->getWidget()->setCursor(aCursor); } -void View3DInventor::setCursor(Qt::CursorShape aCursor) +void View3DInventor::restoreOverrideCursor() { - _viewer->getWidget()->setCursor(aCursor); + _viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); } void View3DInventor::dump(const char* filename) diff --git a/src/Gui/View3DInventor.h b/src/Gui/View3DInventor.h index cfc1f9253f..e6aba94f2c 100644 --- a/src/Gui/View3DInventor.h +++ b/src/Gui/View3DInventor.h @@ -107,8 +107,8 @@ public: public Q_SLOTS: /// override the cursor in this view - void setCursor(const QCursor&); - void setCursor(Qt::CursorShape s); + void setOverrideCursor(const QCursor&); + void restoreOverrideCursor(); void dump(const char* filename); diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index cc83bdaa0d..1bc39d291a 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -1046,7 +1046,7 @@ void CmdMeshRemoveCompByHand::activated(int iMsg) if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); - //viewer->setEditingCursor(QCursor(Gui::BitmapFactory().pixmap("mesh_pipette"),4,29)); + viewer->setEditingCursor(QCursor(Qt::OpenHandCursor)); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), MeshGui::ViewProviderMeshFaceSet::markPartCallback); } } From a5474182b93ae816c0ee7574e982ef68ab3fe46a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 11 Apr 2013 11:23:39 -0300 Subject: [PATCH 08/53] Arch: fixed errors in webgl exporter --- src/Mod/Arch/importWebGL.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py index a8a8c4a2c9..dbb49b7d9c 100644 --- a/src/Mod/Arch/importWebGL.py +++ b/src/Mod/Arch/importWebGL.py @@ -110,6 +110,38 @@ def getObjectData(obj): # print result return result + elif obj.isDerivedFrom("Mesh::Feature"): + mesh = obj.Mesh + result = "var geom = new THREE.Geometry();\n" + + # adding vertices data + for p in mesh.Points: + v = p.Vector + i = p.Index + result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n" + result += tab+"console.log(geom.vertices)\n" + for p in mesh.Points: + result += tab+"geom.vertices.push(v"+str(p.Index)+");\n" + + # adding facets data + for f in mesh.Facets: + result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n" + + # adding material + col = obj.ViewObject.ShapeColor + rgb = Draft.getrgb(col,testbw=False) + #rgb = "#888888" # test color + result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + + # adding the mesh to the scene + result += tab+"var mesh = new THREE.Mesh( geom, material );\n" + result += tab+"scene.add( mesh );\n"+tab + + # print result + return result + + return "" + def getTestData(): "returns a simple cube as three.js snippet" From 521407eb49ee626c1d80a70a11ad23df767122ce Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 11 Apr 2013 14:20:50 -0300 Subject: [PATCH 09/53] 0001042: Draft DXF export with projection direction The DXF exporter now features an option in Draft preferences to project the selected objects along the current view direction on export. --- src/Mod/Draft/Draft.py | 38 +- src/Mod/Draft/DraftGeomUtils.py | 114 ++++- src/Mod/Draft/Draft_rc.py | 423 +++++++++--------- .../Draft/Resources/ui/userprefs-import.ui | 20 + src/Mod/Draft/importDXF.py | 92 +++- 5 files changed, 394 insertions(+), 293 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8d2a39a973..296ea3f6a2 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -3371,42 +3371,6 @@ class _Shape2DView(_DraftObject): if prop in ["Projection","Base","ProjectionMode","FaceNumbers"]: self.createGeometry(obj) - def clean(self,shape): - "returns a valid compound of edges, by recreating them" - # this is because the projection algorithm somehow creates wrong shapes. - # they dispay fine, but on loading the file the shape is invalid - import Part,DraftGeomUtils - oldedges = shape.Edges - newedges = [] - for e in oldedges: - try: - if DraftGeomUtils.geomType(e) == "Line": - newedges.append(e.Curve.toShape()) - elif DraftGeomUtils.geomType(e) == "Circle": - if len(e.Vertexes) > 1: - mp = DraftGeomUtils.findMidpoint(e) - a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape() - newedges.append(a) - else: - newedges.append(e.Curve.toShape()) - elif DraftGeomUtils.geomType(e) == "Ellipse": - if len(e.Vertexes) > 1: - a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape() - newedges.append(a) - else: - newedges.append(e.Curve.toShape()) - elif DraftGeomUtils.geomType(e) == "BSplineCurve": - if DraftGeomUtils.isLine(e.Curve): - l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape() - newedges.append(l) - else: - newedges.append(e.Curve.toShape()) - else: - newedges.append(e) - except: - print "Debug: error cleaning edge ",e - return Part.makeCompound(newedges) - def getProjected(self,obj,shape,direction): "returns projected edges from a shape and a direction" import Part,Drawing @@ -3420,7 +3384,7 @@ class _Shape2DView(_DraftObject): for g in groups[5:]: edges.append(g) #return Part.makeCompound(edges) - return self.clean(Part.makeCompound(edges)) + return DraftGeomUtils.cleanProjection(Part.makeCompound(edges)) def createGeometry(self,obj): import DraftGeomUtils diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index f378baf267..1ae0d693f7 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -195,30 +195,13 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F returns a list containing the intersection point(s) of 2 edges. You can also feed 4 points instead of edge1 and edge2''' - pt1 = None - - if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector): - # we got points directly - pt1 = edge1 - pt2 = edge2 - pt3 = infinite1 - pt4 = infinite2 - infinite1 = ex1 - infinite2 = ex2 - - elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") : - # we have 2 straight lines - pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point, - edge1.Vertexes[1].Point, - edge2.Vertexes[0].Point, - edge2.Vertexes[1].Point] - + def getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2): if pt1: - # first check if we don't already have coincident endpoints - if (pt1 in [pt3,pt4]): - return [pt1] - elif (pt2 in [pt3,pt4]): - return [pt2] + # first check if we don't already have coincident endpoints + if (pt1 in [pt3,pt4]): + return [pt1] + elif (pt2 in [pt3,pt4]): + return [pt2] norm1 = pt2.sub(pt1).cross(pt3.sub(pt1)) norm2 = pt2.sub(pt4).cross(pt3.sub(pt4)) if not DraftVecUtils.isNull(norm1): @@ -250,6 +233,26 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F return [] # Lines have same direction else : return [] # Lines aren't on same plane + + pt1 = None + + if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector): + # we got points directly + pt1 = edge1 + pt2 = edge2 + pt3 = infinite1 + pt4 = infinite2 + infinite1 = ex1 + infinite2 = ex2 + return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2) + + elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") : + # we have 2 straight lines + pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point, + edge1.Vertexes[1].Point, + edge2.Vertexes[0].Point, + edge2.Vertexes[1].Point] + return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2) elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Line") \ or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle") : @@ -1667,6 +1670,71 @@ def filletWire(aWire,r,chamfer=False): filEdges[-1:] = result[0:2] filEdges[0] = result[2] return Part.Wire(filEdges) + +def getCircleFromSpline(edge): + "returns a circle-based edge from a bspline-based edge" + if geomType(edge) != "BSplineCurve": + return None + if len(edge.Vertexes) != 1: + return None + # get 2 points + p1 = edge.Curve.value(0) + p2 = edge.Curve.value(math.pi/2) + # get 2 tangents + t1 = edge.Curve.tangent(0)[0] + t2 = edge.Curve.tangent(math.pi/2)[0] + # get normal + n = p1.cross(p2) + if DraftVecUtils.isNull(n): + return None + # get rays + r1 = DraftVecUtils.rotate(t1,math.pi/2,n) + r2 = DraftVecUtils.rotate(t2,math.pi/2,n) + # get center (intersection of rays) + i = findIntersection(p1,p1.add(r1),p2,p2.add(r2),True,True) + if not i: + return None + c = i[0] + r = (p1.sub(c)).Length + circle = Part.makeCircle(r,c,n) + #print circle.Curve + return circle + +def cleanProjection(shape): + "returns a valid compound of edges, by recreating them" + # this is because the projection algorithm somehow creates wrong shapes. + # they dispay fine, but on loading the file the shape is invalid + oldedges = shape.Edges + newedges = [] + for e in oldedges: + try: + if geomType(e) == "Line": + newedges.append(e.Curve.toShape()) + elif geomType(e) == "Circle": + if len(e.Vertexes) > 1: + mp = findMidpoint(e) + a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape() + newedges.append(a) + else: + newedges.append(e.Curve.toShape()) + elif geomType(e) == "Ellipse": + if len(e.Vertexes) > 1: + a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape() + newedges.append(a) + else: + newedges.append(e.Curve.toShape()) + elif geomType(e) == "BSplineCurve": + if isLine(e.Curve): + l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape() + newedges.append(l) + else: + newedges.append(e.Curve.toShape()) + else: + newedges.append(e) + except: + print "Debug: error cleaning edge ",e + return Part.makeCompound(newedges) + # circle functions ********************************************************* diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 37e3e5fc2e..995e6ab1b5 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Tue Apr 2 18:58:00 2013 +# Created: Thu Apr 11 13:50:17 2013 # by: The Resource Compiler for PyQt (Qt v4.8.2) # # WARNING! All changes made in this file will be lost! @@ -41254,159 +41254,164 @@ qt_resource_data = "\ \x00\x6c\x00\x6b\x00\x79\x08\x00\x00\x00\x00\x06\x00\x00\x00\x11\ \x64\x72\x61\x66\x74\x20\x43\x6f\x6d\x6d\x61\x6e\x64\x20\x42\x61\ \x72\x07\x00\x00\x00\x05\x64\x72\x61\x66\x74\x01\ -\x00\x00\x09\x69\ +\x00\x00\x09\xb5\ \x00\ -\x00\x48\x24\x78\x9c\xed\x5c\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\ -\xe8\xe1\x9c\xb4\xe3\x5a\x92\xaf\x49\x8e\xac\x4e\x62\xd7\x49\x3a\ -\xc9\x69\x5a\xb9\x49\xdf\x3c\x10\x09\x89\xa8\x49\x42\x05\x40\x4b\ -\xea\xaf\xef\x2e\x00\x8a\x14\x45\xdd\x2d\xc9\x71\x35\xe3\x19\x8b\ -\x00\x88\x5d\x2c\xbe\x5d\xec\x2e\x56\x6a\xfc\x38\x88\x42\xf2\xc0\ -\xa4\xe2\x22\xbe\xac\xd4\x8f\x6a\x15\xc2\x62\x4f\xf8\x3c\xee\x5e\ -\x56\x7e\xbf\xbd\xf9\xe1\x65\xe5\xc7\xe6\x41\x23\xe1\xd9\xa0\x53\ -\x18\xd4\x3c\x20\x0d\x2f\xa4\x4a\x35\xdf\x25\xfc\xf5\xeb\x6b\x4e\ -\x43\xd1\x85\xff\x61\xb7\xc5\xb4\x86\x97\xd5\xb5\xa4\x1d\xdd\xa8\ -\xda\x41\x30\xba\xcf\xfd\x2e\xd3\xc4\x3c\x5f\x56\x7e\xfd\x6a\x1e\ -\x2b\x24\xa6\x11\xbb\xac\xcc\x9c\x04\x89\x91\x46\x4f\x8a\x1e\x93\ -\x7a\xe8\xde\xe8\x32\x11\x31\x2d\x87\xa6\x93\x34\x24\xf3\xb4\xf9\ -\x44\x1a\x83\x66\xad\x51\x1d\xb8\x87\x21\x3e\x0c\xdd\x03\xb0\xa0\ -\x83\xe6\xd9\xc5\x59\xa3\x6a\x3f\xda\xe6\x80\xf1\x6e\xa0\x9b\xe7\ -\xc7\xaf\x1a\x55\xf7\xd9\xcc\x59\x4d\x27\x6d\x54\x53\xe2\x65\x9c\ -\xf4\x79\xec\x8b\xfe\x2d\xd7\x21\x73\xcc\x28\x2d\x81\xf9\xe6\x87\ -\xa8\x27\xa4\xae\xfe\x34\xc0\x7f\x8d\xaa\x6b\x9d\x9c\x2f\xa4\x43\ -\x91\x64\x92\xf9\xf2\x56\x0c\x3e\x9a\x26\x37\x5d\x81\x9e\xea\x51\ -\x0f\x26\xaa\x38\xee\xe3\x24\x6a\x33\xd9\x3c\x6f\x54\xdd\x27\xcb\ -\x7b\x9e\xc2\xc4\x14\x11\x95\x5d\x1e\x17\x66\x78\x35\x73\x06\xae\ -\x59\x94\x89\x31\xbf\x93\xef\xa4\x48\x7a\xc0\xf3\x68\x2f\xdd\x73\ -\xfd\xd8\x11\x98\x20\xaf\x33\x59\xe5\xc4\x75\xfd\xc7\x0d\xe9\x08\ -\x19\x51\x4d\x44\x4f\x03\xd2\x54\x5e\x66\x93\x2c\xcd\x97\xdc\x5c\ -\xe1\x4d\x95\x5f\x19\xb5\xd9\x52\x9c\x2a\xc8\xf2\xa9\x32\x71\x96\ -\xac\xe3\xfd\xe4\x3a\x16\x58\xc9\x8c\xb5\x94\xb1\x30\x7f\x3d\xd9\ -\x84\xb5\x05\x27\x1c\x5b\xd5\x24\x52\x3e\xd2\x36\x0b\x53\x98\x68\ -\x36\xd0\xa6\xa1\x7e\x77\x92\xa7\x39\x89\x16\x18\x38\x36\xa0\xa0\ -\x60\x44\xe9\x61\xc8\x0a\x58\x99\xca\x23\x31\xba\x0f\x5c\xe5\x97\ -\x32\xce\xf7\x9c\x65\x18\x5b\xf5\x59\xb2\xce\x95\x88\xda\x22\x07\ -\xfc\x2e\x76\xf4\xa0\xc3\xc3\x8e\x36\x74\xcc\x5c\x96\x10\xe1\x2d\ -\xef\x95\xaf\xec\x36\xe0\x8a\xc0\x9f\x0e\x18\x01\x33\x17\x08\x9f\ -\x78\x81\x10\x8a\xf9\xa8\x22\x84\x9b\x85\xc3\x40\x02\x0f\x5a\xd2\ -\x58\x85\xd4\x3c\xa2\x0e\x89\xf6\x9f\x60\xb7\x88\x27\x42\x1c\x19\ -\x6b\x41\x6e\x24\x63\x57\x6f\xae\x8f\xc8\xc1\x87\x8e\x6b\x8f\x68\ -\xaf\x87\x2f\x00\x0d\x37\xf1\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\ -\x5a\x18\xdb\xe1\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x48\x8b\x98\ -\x68\xda\x86\x6e\x1d\x80\xfa\xf6\x79\x18\xe2\x40\x38\x31\x1c\x1f\ -\xca\x32\x12\xf2\x98\x19\xcb\xab\x8e\x0e\x16\xde\xb0\x09\xc9\x79\ -\x89\x94\x2c\xd6\x1f\x62\x9f\x0d\x0a\xe2\x9b\x8e\xd7\x45\x27\xc7\ -\xfd\xfb\x29\xc6\x83\x05\x70\xe5\x2b\xa6\x2f\x2b\xb5\x02\x11\xcf\ -\x31\xee\x0f\x3a\x0e\x7a\xde\xaa\x4b\x41\x6a\x9f\xa9\x0e\xe6\x13\ -\xfb\x24\xfc\x6a\x7a\xa4\x2e\x4c\xad\x00\xe4\x45\x74\x6b\x04\xc1\ -\xff\x8b\x98\x91\x17\x1d\xaa\x34\x53\xfa\xbb\xb2\xdd\x9a\x46\xb5\ -\x5a\x24\xbb\x16\x1f\xbf\x03\x12\x7d\xd6\xa1\x49\x98\x62\x9a\xc6\ -\x7e\x86\xa4\xdd\x31\xf6\x8b\xe4\x60\x2e\x69\xf8\xb4\xb8\xba\x1a\ -\xa9\x2c\xd8\x8a\xbc\xca\xed\x90\x25\xc9\xa8\x66\xa4\x47\x25\x45\ -\x97\x8d\x7b\xce\x44\x15\xcf\xf7\xed\xb3\xd4\xba\x67\xda\x0b\xd8\ -\x5a\x8c\xcc\x3d\x4f\x1a\x55\x7b\xbc\x67\xde\x40\xbe\x7b\x61\x4f\ -\xc0\x2d\x2a\x10\x92\xff\x8d\x36\x38\x9c\xf4\x10\x96\x39\x7e\x43\ -\x7c\xb8\xbb\x58\xf1\xe4\xfd\x44\x07\xa4\xd5\x43\x6c\x91\x16\xeb\ -\x46\x60\x8d\x77\x70\xfe\xb6\xe0\x54\x2a\x3b\x7e\x15\xb4\xc3\xe9\ -\x7b\x77\x3c\x73\x71\x11\x1d\xf0\x28\x89\x5a\xfc\x6f\x56\x5c\x23\ -\x34\x15\x60\x63\xc3\x85\xf3\xda\x58\xe0\x30\xea\x75\x41\x43\xfd\ -\xfc\xe2\xe2\xe2\xb8\x7e\x36\x16\x45\x64\x8b\x2c\x4e\xbb\xd8\x09\ -\x31\xd3\x4d\xf8\x1a\xb0\x98\xb0\x41\xea\x0c\x28\xb3\x23\x0a\xd5\ -\x1e\x1c\x81\x43\xf4\x1e\x86\x84\x4a\x66\xcf\x69\xf4\xad\xc1\x26\ -\xf0\x98\xf4\x44\x38\x34\x23\x8f\x88\x71\x34\x1e\x68\x98\xb0\x91\ -\xbb\x61\xe5\x42\x42\x16\x77\x75\x40\x44\x87\x30\xea\x99\xff\xd8\ -\x9b\xbe\x4a\x94\xdd\x76\x98\x02\x7c\x8a\x9a\xa1\x15\x9b\x11\xfd\ -\x40\x80\x1f\x60\x59\x31\x73\x1a\x55\xf3\x09\x55\xe0\x30\x00\xdf\ -\x14\x45\x93\xbe\x7e\xb4\xba\x17\x60\x98\x2e\x3f\xfe\xcf\xb6\x72\ -\xfc\x83\xa0\x9c\xc0\x53\x0d\x78\x9a\x6e\xc0\x8e\x0d\xd4\x98\x77\ -\xbf\xbc\x89\x5a\xd1\x40\x5d\x4d\x78\xae\x3b\x30\x50\x37\x40\xf6\ -\xca\xf8\xd2\x72\xc2\x48\x21\x4b\x9e\xeb\x9b\x69\xa6\xc0\xd7\x5e\ -\xd2\x4c\x9d\xd4\x66\xdb\xa9\xda\xf6\x0c\xd4\x6d\xc0\xca\x82\x88\ -\x4e\x21\x6c\x01\x4f\x7a\x4a\x9c\xb0\xba\x7d\x58\xce\x91\x77\xec\ -\x59\xa0\xec\xf5\xb8\x4c\x8f\x2f\x16\xd7\xe3\x2c\x44\x0e\x98\x77\ -\x5f\x1a\x22\x63\xc7\xfc\x43\x7a\x26\xb8\x38\x1e\x49\x36\x4e\x4e\ -\x62\x33\x21\x46\xb1\x68\x13\x54\x35\x32\xff\x48\x5f\xc4\xff\xd5\ -\xa4\xcd\x5c\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x29\x62\x18\xe0\ -\x73\x38\x0f\x54\x49\x06\x6b\x49\x28\x2d\x0e\x5f\xa4\xbd\xc7\x6d\ -\x39\x6e\x8f\x37\x82\xdb\x39\x39\xab\x05\x71\x3b\x42\x6d\x8f\xc2\ -\xeb\x04\x73\x7a\x2c\x8d\x8e\x6c\x1a\x25\x87\x5d\xf0\xeb\xc4\x06\ -\xf1\x6b\x25\xbb\x35\xc8\x5a\x72\x7b\xd0\x96\x83\xf6\x74\x23\xa0\ -\x9d\x13\xee\xcd\x02\xad\x99\xdc\xe1\xb6\x63\x52\x85\x7d\x1a\x6b\ -\xe3\xf1\xc7\x22\xfe\x01\x67\xf0\x49\x3b\x14\xde\xbd\x22\x2f\xda\ -\xac\xcb\x63\x93\x23\xec\x73\x88\x21\x28\xf9\xfe\x3b\x0c\x4a\xb6\ -\x87\xe5\xef\x2d\x27\xdb\xc2\xb2\xd2\x54\xa6\x14\xf7\x78\x2e\xc3\ -\xf3\xcb\x8d\xe0\xf9\xec\x71\x8d\x70\x6a\x78\x3b\x52\x44\x06\xd9\ -\x0a\xe6\x41\xbb\xc8\x64\x66\x8d\xff\x14\xe0\x9c\xfa\xd6\x4f\x35\ -\x9b\x40\xde\x9a\x9d\x07\xcf\x23\x91\x06\xf3\xf8\xa6\xcf\x21\x36\ -\xa4\x43\x62\xf2\xa7\xf2\x90\xb4\x41\x5c\x11\xbd\x77\xdd\x18\x5d\ -\x2b\x05\x81\xb5\xe2\xe1\x90\x30\x9f\x9b\xe4\xf9\x26\xf4\xc1\x5c\ -\xc6\xa5\x4b\x30\x3c\x6f\x51\x33\xba\x48\xfc\xa3\xa1\xbd\xd7\x8b\ -\x72\xbd\x38\xdb\x88\x5e\xbc\x5a\x5d\x2f\xf0\x86\x28\xd5\x87\x8e\ -\x64\xcc\xa3\xbe\x85\x3e\xec\x38\xda\x70\x84\x3f\x26\xe2\x79\xec\ -\x71\x9f\xc1\xc7\x54\x69\x0c\xb8\xfa\x5c\x62\x56\xe9\x2d\xeb\x53\ -\xc9\x0e\xad\x86\x79\x14\x2f\x87\xee\xf1\x3e\xa9\x1f\x40\x7c\x75\ -\x74\xb4\x46\xd6\x67\x3a\xd2\x7f\x06\x96\x48\x5a\x15\xb0\x15\x78\ -\xa3\x28\x32\x82\x7b\x7c\x97\xe1\xfb\x7c\x13\xf8\x5e\x0b\xdd\x13\ -\x56\x9f\x02\xb8\x53\x10\xe7\x6e\x37\x3b\xe0\x8a\x67\x56\xdf\x26\ -\x59\x6d\x1a\xf3\xc4\x37\x69\x50\x33\x60\x13\x48\xb6\x05\x23\xe4\ -\xe4\x7a\xc4\x16\x10\x4d\x29\x92\x88\xa9\x29\x37\x16\x1b\xc9\x8b\ -\x00\xb5\x3d\xb6\xcb\xb1\x5d\xaf\x6f\xc4\x78\xbf\x7c\x5c\x78\x67\ -\x1e\xb7\xcd\x88\x20\xa0\x91\x31\xe3\xdf\x68\x1a\xfb\x54\xfa\xce\ -\x91\xc1\x11\x04\xb3\x80\xf0\x56\x0c\x7e\x0b\x98\x7e\x97\xf6\xc7\ -\x46\x7b\x9d\x10\xd0\x07\x86\x77\x08\xd8\x8a\xd5\x06\xbe\xf0\x92\ -\xa5\xee\x7f\x96\x50\x04\xbc\xfa\x1d\xb1\xd8\x01\xd1\x5b\x3e\x4c\ -\xf6\x10\x17\xb3\x2d\x25\x68\x69\x1f\xf3\xaf\x7b\x3d\x98\xa2\x07\ -\x9b\xc9\xb0\xd4\x6b\x8f\xab\x08\x01\x35\x77\xbd\x23\x93\xee\x0a\ -\x54\x52\x5f\x5e\x81\xa2\x84\xcc\x7a\x30\x1b\x8c\x4c\x0d\x17\xa4\ -\x2d\x12\x44\x35\x67\xc6\xb6\xaf\x49\x73\x09\x30\x5b\x63\x70\x3d\ -\xe8\xbc\xa7\xee\xe2\x7b\x0f\xe9\x52\x48\x2f\x71\x69\xb5\x0c\xa4\ -\xeb\x8f\x0b\xe9\x3e\x5e\xba\x8e\x6e\x73\xad\x6d\x06\x2f\x1b\x6f\ -\x4e\xb0\x66\x06\x03\x55\x77\x0b\x9c\x82\x5e\xb2\xd8\x67\xd2\xfa\ -\x31\x5e\x68\x0a\xca\x0c\xfa\x6c\xa2\x46\x9b\xeb\x1a\x89\x75\xaf\ -\x64\x6a\xd1\xc8\xba\x8a\xf0\x9b\x61\x21\xc7\xb6\x21\xbd\x26\xb9\ -\x25\x74\xc0\x8a\xe0\xb3\x23\xff\xd5\xd2\x7d\x8e\x6a\x30\xde\x39\ -\x36\x57\x6e\xdc\x4a\x95\xbd\x77\x4b\xd6\xf6\xb6\xbe\xbc\x7b\xbc\ -\xda\x5e\x47\x29\x97\x82\xff\xd6\xab\x7c\xd3\x15\x8d\x65\x7d\x9f\ -\x6f\xbd\xef\x9c\xb4\xdd\xce\xeb\x7d\xcd\x35\x8c\x9c\x38\x1b\x5a\ -\xa6\x79\x2c\xa4\x9d\xe4\x1e\x46\x83\x37\x6c\x4a\x62\x0b\x8b\x60\ -\x20\xd2\xe6\xaf\xfa\xf5\xeb\xf7\xa3\x19\x1b\x55\xd3\xb8\xb4\xd1\ -\x41\x37\xf8\x3d\x78\x2d\xd3\x8d\xce\xd4\xe2\x80\xd3\xd9\xb5\x01\ -\xc7\x6b\x15\x07\xc0\x30\x23\xa3\x25\x64\xbd\x6a\x6d\xf5\x3a\x17\ -\x70\x0b\x57\x57\xa3\xd9\x9a\x5e\x4e\xfd\xed\x57\x30\xab\x87\xee\ -\xbe\x82\x79\xe3\xc5\xa6\xff\xba\x0a\xe6\x5d\x7b\xef\xaf\x16\x77\ -\xde\xcb\x8a\x62\xe7\x94\xa4\xcc\xcb\xdb\xb5\x9e\xc8\xd7\x51\x40\ -\xb9\xef\x6c\xda\xf2\xce\x28\xf9\xdd\xfa\x5f\x4b\x31\x4b\xc3\x9c\ -\x90\xf1\xe7\xb0\x92\x0b\x73\xfe\x12\x18\xb4\xa1\x48\x56\x8a\x4a\ -\x5d\x6d\xf5\xf3\x30\x92\x63\x72\x7c\x9e\xc6\xf2\xd6\x95\xe3\xc1\ -\x19\xf8\x02\x0f\xc1\x9e\xc4\x7b\x9e\xff\xd0\xa8\xf7\xbf\xf4\x32\ -\x73\x87\x26\xf4\x37\xda\xb7\x6c\x5d\xbd\xf9\xb4\x16\x1b\xbb\x36\ -\x4d\x63\x49\xad\xc7\x4b\x2c\xcc\xf6\x49\x97\xa9\x21\x47\xcd\x7e\ -\xe0\xac\xaf\x0e\xf1\xbe\x9a\x99\xdb\x91\x7e\x80\x1a\x6e\x8e\x06\ -\x21\xef\x09\x7e\xb7\x84\xa2\x2f\x44\xda\x21\xf5\xee\x0f\x8d\xd3\ -\xd4\x66\x5a\x83\xcf\x2c\x19\xf5\x69\x9b\x87\x1c\x88\xd3\x2e\xc5\ -\x34\xb2\x7b\xbd\x0d\x43\xf1\x42\x38\xf6\x37\x92\x5e\x1b\xe1\x37\ -\xc7\xad\x3b\xd7\xcc\xa5\x37\x50\x5f\xc3\x14\xd9\x84\x4b\x81\x72\ -\x1b\xc4\xda\xd4\x32\x01\x8b\x60\x3e\x6e\xd2\x08\xb5\x1e\xba\x1f\ -\x31\x59\xf2\xd6\x2e\xe4\x69\x5a\xa0\xa7\x9b\xae\x18\x05\x0b\x8b\ -\xa5\x2b\x7e\xb9\x7a\xf3\xf8\xe9\x8a\x4c\x47\x9f\x4b\xba\x62\xac\ -\x22\xf8\x9b\x4f\x57\x2c\x61\x6e\x4f\x57\x37\xb7\x33\xea\xe8\x28\ -\x18\x4f\x45\x5e\x9c\x5c\xdb\xbb\xe7\xb2\x92\xb9\x8d\x54\x4e\xb8\ -\xb4\x0a\x82\xde\xb0\xb0\x95\x2c\xac\xf0\xa8\x23\xb6\xb7\x65\x66\ -\x2f\xf2\x39\x27\xbc\x97\xe2\x5e\x9a\x71\x9a\x66\xbb\xca\x52\x4d\ -\x59\x96\xe9\x8b\x9b\x63\x2c\xc7\x34\x69\xb7\x96\xc8\x2c\x8d\x27\ -\x95\x5c\x3e\xe9\x78\x22\x9f\x94\xa6\x92\x4e\x27\x52\x49\x63\x59\ -\xa4\x22\x2b\x63\xb9\xa3\x4c\x48\x39\x49\xe6\xc4\xe8\x8c\x53\x1a\ -\x55\x3b\x63\x73\x59\x39\xaf\x10\x6b\x26\x2e\x2b\xf5\x7a\xa5\x8a\ -\x23\x7b\x7c\x10\xd1\x5e\x27\x89\x3d\x14\x54\xf3\xaf\xcf\xe6\xf9\ -\x46\x8a\xe8\x13\x8f\x58\x4b\x24\xd2\x83\x03\xbc\x30\x0a\x7f\xdd\ -\x24\x51\x5a\x44\x96\xa2\x32\x9c\xe4\x5b\x2c\x97\xb9\x5f\x40\xc9\ -\x7d\xd7\x27\xfb\xd1\x13\xdc\x8f\x81\x66\xe0\xf2\x34\xdd\x0f\x9e\ -\xc0\x6e\xb8\x86\x03\x2b\x2a\xea\xc3\x92\x61\x86\x2a\x4e\x60\x7f\ -\x01\xe5\x28\x40\xc1\x99\x0e\x23\x80\x22\xdd\xd9\x8c\x14\xbe\x78\ -\x54\xca\xcc\x24\xc7\xd3\xb8\xc2\xd9\x2c\xe7\x6a\x7d\xb6\xdc\x17\ -\x36\xcb\xe5\x33\xea\xdc\x0a\x2b\xa9\x8d\x2f\xe7\x25\xeb\xdd\x0e\ -\x33\x2e\x72\x9f\xc2\xcc\xa8\x77\x7d\x66\xc6\x1b\xcc\xef\xf2\x48\ -\xa6\x8c\x0e\x28\xa3\x2d\x9e\x88\x63\x66\x74\x00\x9f\x1b\xd5\x84\ -\x37\x0f\xfe\x01\xbd\x89\x17\xfc\ +\x00\x4b\x27\x78\x9c\xed\x5c\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\ +\xe8\xe1\x34\xed\xb8\x96\xe5\x6b\x92\x23\xab\x93\xd8\x71\x92\x4e\ +\xd2\xba\x95\x9b\x9c\x37\x0f\x44\x42\x22\x6a\x92\x50\x01\xd0\x92\ +\xfa\xeb\xcf\x2e\x00\x8a\x14\x49\xdd\x2d\xd9\xc9\x68\xc6\x33\x16\ +\x01\x10\xbb\x58\x7e\xbb\xd8\x5d\x2c\xd9\xfc\x65\x18\x85\xe4\x81\ +\x49\xc5\x45\x7c\x51\x6b\x1c\x1c\xd6\x08\x8b\x3d\xe1\xf3\xb8\x77\ +\x51\xfb\xeb\xf6\xfa\xe7\x97\xb5\x5f\x5a\x7b\xcd\x84\x67\x83\x4e\ +\x60\x50\x6b\x8f\x34\xbd\x90\x2a\xd5\x7a\x9f\xf0\xd7\xaf\xaf\x38\ +\x0d\x45\x0f\xfe\x87\xbd\x36\xd3\x1a\x6e\x56\x57\x92\x76\x75\xb3\ +\x6e\x07\xc1\xe8\x01\xf7\x7b\x4c\x13\x73\x7d\x51\xfb\xe3\xab\xb9\ +\xac\x91\x98\x46\xec\xa2\x36\x73\x12\x24\x46\x9a\x7d\x29\xfa\x4c\ +\xea\x91\xbb\xa3\xc7\x44\xc4\xb4\x1c\x99\x4e\xd2\x94\xcc\xd3\xe6\ +\x17\x69\x0e\x5b\x87\xcd\xfa\xd0\x5d\x8c\xf0\x62\xe4\x2e\x80\x05\ +\x1d\xb4\x4e\xcf\x4f\x9b\x75\xfb\xd3\x36\x07\x8c\xf7\x02\xdd\x3a\ +\x3b\x7a\xd5\xac\xbb\xdf\x66\xce\x7a\x3a\x69\xb3\x9e\x12\xaf\xe2\ +\x64\xc0\x63\x5f\x0c\x6e\xb9\x0e\x99\x63\x46\x69\x09\xcc\xb7\x3e\ +\x46\x7d\x21\x75\xfd\xdd\x10\xff\x35\xeb\xae\xb5\x3c\x5f\x48\x47\ +\x22\xc9\x24\xf3\xe5\xad\x18\x7e\x32\x4d\x6e\xba\x02\x3d\xd5\xa7\ +\x1e\x4c\x54\x73\xdc\xc7\x49\xd4\x61\xb2\x75\xd6\xac\xbb\x5f\x96\ +\xf7\x3c\x85\xd2\x14\x11\x95\x3d\x1e\x17\x66\x78\x35\x73\x06\xae\ +\x59\x94\x89\x31\xff\x24\xdf\x4b\x91\xf4\x81\xe7\xf1\xb3\x74\xd7\ +\x8d\x23\x47\xa0\x44\x5e\x67\xb2\xca\x89\xeb\xea\x7f\xd7\xa4\x2b\ +\x64\x44\x35\x11\x7d\x0d\x48\x53\x79\x99\x95\x59\x9a\x2f\xb9\xb9\ +\xc2\x9b\x2a\xbf\x2a\x6a\xb3\xa5\x38\x55\x90\xd5\x53\x65\xe2\xac\ +\x58\xc7\x87\xf2\x3a\x16\x58\xc9\x8c\xb5\x54\xb1\x30\x7f\x3d\xd9\ +\x84\x87\x0b\x4e\x38\xb1\xaa\x32\x52\x3e\xd1\x0e\x0b\x53\x98\x68\ +\x36\xd4\xa6\xa1\x71\x77\x9c\xa7\x59\x46\x0b\x0c\x9c\x18\x50\x50\ +\x30\xa2\xf4\x28\x64\x05\xac\x4c\xe5\x91\x18\xdd\x07\xae\xf2\x4b\ +\x99\xe4\x7b\xce\x32\x8c\xad\xba\x91\xac\x7b\x29\xa2\x8e\xc8\x01\ +\xbf\x87\x1d\x7d\xe8\xf0\xb0\xa3\x03\x1d\x33\x97\x25\x44\x78\xcb\ +\xfb\xd5\x2b\xbb\x0d\xb8\x22\xf0\xa7\x03\x46\xc0\xcc\x05\xc2\x27\ +\x5e\x20\x84\x62\x3e\xaa\x08\xe1\x66\xe1\x30\x90\xc0\x85\x96\x34\ +\x56\x21\x35\x97\xa8\x43\xa2\xf3\x37\xd8\x2d\xe2\x89\x10\x47\xc6\ +\x5a\x90\x6b\xc9\xd8\xe5\x9b\xab\x03\xb2\xf7\xb1\xeb\xda\x23\xda\ +\xef\xe3\x0d\x40\xc3\x4d\xbc\x4f\x00\x70\x24\x4a\x94\x76\x2d\x84\ +\x16\xc6\x76\x79\xc8\xa0\x29\xd6\x94\xc7\x78\x4d\x33\xd2\x22\x26\ +\x9a\x76\xa0\x5b\x07\xa0\xbe\x03\x1e\x86\x38\x10\x76\x0c\xc7\x87\ +\xb2\x8c\x84\x3c\x66\xc6\xf2\xaa\x83\xbd\x85\x1f\x58\x49\x72\x5e\ +\x22\x25\x8b\xf5\xc7\xd8\x67\xc3\x82\xf8\xa6\xe3\x75\xd1\xc9\xf1\ +\xf9\xbd\x8b\x71\x63\x01\x5c\xf9\x8a\xe9\x8b\xda\x61\x81\x88\xe7\ +\x18\xf7\x87\x5d\x07\x3d\x6f\xd5\xa5\x20\xb5\x1b\xaa\x83\xf9\xc4\ +\x3e\x0b\xbf\x9e\x6e\xa9\x0b\x53\x2b\x00\x79\x11\xdd\x1a\x43\xf0\ +\x37\x11\x33\xf2\xa2\x4b\x95\x66\x4a\xff\x58\xf5\xb4\xa6\x51\xad\ +\x17\xc9\xae\xc5\xc7\x5f\x80\x44\x9f\x75\x69\x12\xa6\x98\xa6\xb1\ +\x9f\x21\xe9\xe9\x18\xfb\x5d\x72\x30\x97\x34\x7c\x5e\x5c\x5d\x8e\ +\x55\x16\x6c\x45\x5e\xe5\x9e\x90\x25\xc9\xa8\x66\xa4\x4f\x25\x45\ +\x97\x8d\x7b\xce\x44\x15\xf7\xf7\xed\xb3\xd4\xbe\x67\xda\x0b\xd8\ +\x5a\x8c\xcc\xdd\x4f\x9a\x75\xbb\xbd\x67\xde\x40\xbe\x7b\x61\x4f\ +\xc0\x2d\x2a\x10\x92\xff\x8b\x36\x38\x2c\x7b\x08\xcb\x6c\xbf\x21\ +\x5e\xdc\x9d\xaf\xb8\xf3\x7e\xa6\x43\xd2\xee\x23\xb6\x48\x9b\xf5\ +\x22\xb0\xc6\x4f\xb0\xff\xb6\x61\x57\xaa\xda\x7e\x15\xb4\xc3\xee\ +\x7b\x77\x34\x73\x71\x11\x1d\xf2\x28\x89\xda\xfc\x5f\x56\x5c\x23\ +\x34\x15\x60\x63\xc3\x85\xb3\xc3\x89\xc0\x61\xdc\xeb\x82\x86\xc6\ +\xd9\xf9\xf9\xf9\x51\xe3\x74\x22\x8a\xc8\x16\x59\x9c\x76\xb1\x1d\ +\x62\xa6\x9b\xf0\x35\x60\x31\x61\xc3\xd4\x19\x50\xe6\x89\x28\x54\ +\x7b\x70\x04\xf6\xd1\x7b\x18\x11\x2a\x99\xdd\xa7\xd1\xb7\x06\x9b\ +\xc0\x63\xd2\x17\xe1\xc8\x8c\x3c\x20\xc6\xd1\x78\xa0\x61\xc2\xc6\ +\xee\x86\x95\x0b\x09\x59\xdc\xd3\x01\x11\x5d\xc2\xa8\x67\xfe\x63\ +\x6f\x7a\x2b\x51\xf6\xb1\xc3\x14\xe0\x53\x1c\x1a\x5a\xb1\x19\x31\ +\x08\x04\xf8\x01\x96\x15\x33\xa7\x51\x35\x9f\x50\x05\x0e\x03\xf0\ +\x4d\x51\x34\xe9\xed\x07\xab\x7b\x01\x86\xe9\xea\xed\xff\x74\x2b\ +\xdb\x3f\x08\xca\x09\x3c\xd5\x80\xe7\xe9\x06\x3c\xb1\x81\x9a\xf0\ +\xee\x97\x37\x51\x2b\x1a\xa8\xcb\x92\xe7\xfa\x04\x06\xea\x1a\xc8\ +\x5e\x1a\x5f\x5a\x96\x8c\x14\xb2\xe4\xb9\xbe\x99\x66\x0a\x7c\xed\ +\x25\xcd\xd4\xf1\xe1\x6c\x3b\x75\xb8\x3d\x03\x75\x1b\xb0\xaa\x20\ +\xa2\x5b\x08\x5b\xc0\x93\x9e\x12\x27\xac\x6e\x1f\x96\x73\xe4\x1d\ +\x7b\x16\x28\x3b\x3d\xae\xd2\xe3\xf3\xc5\xf5\x38\x0b\x91\x03\xe6\ +\xdd\x57\x86\xc8\xd8\x31\x7f\x93\x9e\x09\x2e\x8e\x5b\x92\x8d\x93\ +\x93\xd8\x4c\x88\x51\x2c\xda\x04\x55\x8f\xcc\x3f\x32\x10\xf1\x0f\ +\x9a\x74\x98\x8b\x98\x99\xbf\x3a\x9e\xe6\xa6\x21\x2c\x45\x0c\x03\ +\x7c\x0e\xfb\x81\xaa\xc8\x60\x2d\x09\xa5\xc5\xe1\x8b\xb4\x77\xb8\ +\xad\xc6\xed\xd1\x46\x70\x3b\x27\x67\xb5\x20\x6e\xc7\xa8\xed\x53\ +\xb8\x9d\x60\x4e\x8f\xa5\xd1\x91\x4d\xa3\xe4\xb0\x0b\x7e\x9d\xd8\ +\x20\x7e\xad\x64\xb7\x06\x59\x4b\x6e\x07\xda\x6a\xd0\x9e\x6c\x04\ +\xb4\x73\xc2\xbd\x59\xa0\x35\x93\x3b\xdc\x76\x4d\xaa\x70\x40\x63\ +\x6d\x3c\xfe\x58\xc4\x3f\xe3\x0c\x3e\xe9\x84\xc2\xbb\x57\xe4\x45\ +\x87\xf5\x78\x6c\x72\x84\x03\x0e\x31\x04\x25\x3f\xfd\x88\x41\xc9\ +\xf6\xb0\xfc\x93\xe5\x64\x5b\x58\x56\x9a\xca\x94\xe2\x0e\xcf\x55\ +\x78\x7e\xb9\x11\x3c\x9f\x3e\xae\x11\x4e\x0d\x6f\x57\x8a\xc8\x20\ +\x5b\xc1\x3c\x68\x17\x99\xcc\xac\xf1\xdf\x02\x9c\x53\xdf\xfa\xa9\ +\xe6\x21\x90\xb7\xe6\xc9\x83\xe7\x91\x48\x83\x79\xbc\xd3\xe7\x10\ +\x1b\xd2\x11\x31\xf9\x53\xb9\x4f\x3a\x20\xae\x88\xde\xbb\x6e\x8c\ +\xae\x95\x82\xc0\x5a\xf1\x70\x44\x98\xcf\x4d\xf2\x7c\x13\xfa\x60\ +\x0e\xe3\xd2\x25\x18\x9e\xb7\xa8\x19\x3d\x24\xfe\xc9\xd0\xde\xe9\ +\x45\xb5\x5e\x9c\x6e\x44\x2f\x5e\xad\xae\x17\x78\x42\x94\xea\x43\ +\x57\x32\xe6\x51\xdf\x42\x1f\x9e\x38\xda\x70\x84\x3f\x26\xe2\x79\ +\xec\x71\x9f\xc1\xcf\x54\x69\x0c\xb8\x06\x5c\x62\x56\xe9\x2d\x1b\ +\x50\xc9\xf6\xad\x86\x79\x14\x0f\x87\xee\xf1\x3c\x69\x10\x40\x7c\ +\x75\x70\xb0\x46\xd6\x67\x3a\xd2\x7f\x05\x96\x48\x5a\x15\xb0\x15\ +\x78\xa3\x28\x32\x82\x3b\x7c\x57\xe1\xfb\x6c\x13\xf8\x5e\x0b\xdd\ +\x25\xab\x4f\x01\xdc\x29\x88\x73\xa7\x9b\x5d\x70\xc5\x33\xab\x6f\ +\x93\xac\x36\x8d\x79\xec\x9b\x34\xa8\x19\xb0\x09\x24\xdb\x82\x11\ +\x72\x7c\x35\x66\x0b\x88\xa6\x14\x49\xc4\xd4\x94\x13\x8b\x8d\xe4\ +\x45\x80\xda\x0e\xdb\xd5\xd8\x6e\x6c\xc6\x49\x6f\xac\x91\x12\xa9\ +\xc2\x37\xba\x23\x63\xf8\x16\x63\x4b\x98\x1c\x1b\xec\x59\x21\x70\ +\x11\x62\xe9\x00\xde\xe1\x0e\xd9\xc9\x03\x67\x03\xf0\x66\xb0\x14\ +\x8a\x8b\x78\x13\x70\xbf\xb1\x2c\x94\x79\xa4\xa1\x00\x3d\x7c\x6c\ +\x46\x96\xc3\xbf\x93\xcf\x4e\x05\xa6\xa8\x40\x63\x23\x2a\xf0\xf2\ +\x71\x35\x20\x0b\x3a\x6d\x52\x10\xb1\x8f\x8c\x19\x17\x5f\xd3\xd8\ +\xa7\xd2\x77\xbe\x3c\x8e\x20\x98\x08\x87\xbb\x62\x70\xdd\xc1\xfb\ +\x71\x27\x5f\xd8\x68\x4f\xd4\x02\xfa\xc0\xf0\x18\x0d\x5b\xb1\xe0\ +\xc6\x17\x5e\xb2\xd4\x11\xe8\x12\xca\x81\xd5\x0f\x63\x16\xbb\x20\ +\x7a\xcb\x87\x49\xa0\xe3\x62\xb6\xa5\x07\x6d\xed\xe3\x11\xc4\x4e\ +\x0f\xa6\xe8\xc1\x66\x92\x8c\x8d\xc3\xc7\x55\x84\x80\x9a\x72\x87\ +\xb1\xf5\x77\x35\x5a\x69\x38\xab\x40\x51\x42\x66\x9d\xf8\x0d\x26\ +\x67\x0c\x17\xa4\x23\x12\x44\x35\x67\xc6\xbd\x59\x93\xe6\x12\x60\ +\xb6\xc6\xe0\x6a\xd8\xfd\x40\x5d\xed\xc7\x0e\xd2\x95\x90\x5e\xe2\ +\xdc\x76\x19\x48\x37\x1e\x17\xd2\x03\xac\x3b\x18\x17\x34\x58\xdb\ +\x0c\x81\x26\x1e\x1e\x62\xd9\x18\xe6\x6a\x5c\x21\x44\x0a\x7a\xf0\ +\x26\x7c\x26\xad\x2b\xef\x85\xa6\xa6\xd2\xa0\xcf\xe6\x2a\x8d\xef\ +\x23\x24\xba\x19\x64\x6a\xdd\xd4\xba\x8a\xf0\xa7\x61\x21\xc7\xb6\ +\x21\xbd\x26\xb9\x25\x74\xc0\x8a\xe0\xc6\x91\xff\x6a\xe9\x7e\x8f\ +\x6a\x30\xd9\x39\x31\x57\x6e\xdc\x4a\xc5\xed\x77\x4b\x96\xb7\xb7\ +\xbf\xbc\x7f\xbc\xf2\x76\x47\x29\x77\x0a\xf5\xad\x17\xba\xa7\x2b\ +\x9a\x88\xa9\xe6\xad\x69\xc6\xaa\xaa\xe1\xf4\x6c\x4a\xde\xe7\x64\ +\xae\x9f\xbc\xe4\xdd\x9c\x44\xca\xd2\xde\xd0\x36\xcd\x13\x59\x9d\ +\x32\xf7\x30\x1a\xbc\x61\x53\x15\x5e\x58\x04\x03\x91\xb6\xfe\xd0\ +\xaf\x5f\x7f\x18\xcf\xd8\xac\x9b\xc6\xa5\x8d\x0e\xba\xc1\x1f\xc0\ +\x6b\x99\x6e\x74\xa6\xd6\xc7\x9c\xcc\x2e\x8f\x39\x5a\xab\x3e\x06\ +\x86\x19\x19\x2d\x21\xeb\x55\x5f\x2f\x58\xe7\x0c\x7a\xe1\x17\x0c\ +\xd0\x6c\x4d\x7f\xa3\xe0\xdb\x2f\xe2\x57\x0f\xbd\x5d\x11\xff\x02\ +\x65\xce\xbb\x22\xfe\xa5\xb8\x7a\x6a\xef\xfd\xd5\xe2\xce\x7b\x55\ +\x5d\xf8\x9c\x14\xe4\xbc\xd4\x75\xfb\x99\xbc\x91\x05\xca\x7d\x67\ +\xd3\x8a\x77\x46\xc9\xef\xd6\x7f\x33\xcb\x2c\x0d\x73\x42\xc6\x9f\ +\xc3\x62\x46\x3c\xf6\x92\xc0\xa0\x0d\x45\xb2\x6a\x6c\xea\x5e\x2f\ +\xf8\x3e\x8c\xe4\x84\x1c\xbf\x4f\x63\x79\xeb\x2a\x52\x61\x0f\x7c\ +\x81\x9b\x60\x5f\xe2\x51\xe7\x7f\x68\xd4\xff\x6f\x7a\x9e\xff\x84\ +\x26\xf4\x4f\x3a\xb0\x6c\x5d\xbe\xf9\xbc\x16\x1b\x4f\x6d\x9a\x26\ +\x92\x5a\x8f\x97\x58\x98\xed\x93\x2e\xf3\x1a\x05\x6a\x36\x9e\x36\ +\xa8\x7d\x2c\xd9\x60\xe6\x80\x70\x10\xa0\x86\x9b\xad\x41\xc8\x7b\ +\x82\xaf\x57\x51\xf4\x85\x48\x27\xa4\xde\xfd\xbe\x71\x9a\x3a\x4c\ +\x6b\xf0\x99\x25\xa3\x3e\xed\xf0\x90\x03\x71\xda\xa3\x98\x46\x76\ +\xb7\x77\x60\x28\xd6\x44\xc4\xfe\x46\xd2\x6b\x63\xfc\xe6\xb8\x75\ +\xfb\x9a\xa9\xfb\x00\xea\x6b\x98\x22\x9b\x70\x29\x50\xee\x80\x58\ +\x5b\x5a\x26\x60\x11\xcc\xcf\x4d\x1a\xa1\xf6\x43\xef\x13\x26\x4b\ +\xde\xda\x85\x3c\x4f\x0b\xf4\x7c\xd3\x15\xe3\x60\x61\xb1\x74\xc5\ +\xef\x97\x6f\x1e\x3f\x5d\x91\xe9\xe8\xf7\x92\xae\x98\x28\x8a\xff\ +\xe6\xd3\x15\x4b\x98\xdb\x93\xd5\xcd\xed\x8c\x52\x52\x0a\xc6\x53\ +\x91\x17\xc7\x57\xb6\xfc\xa2\xaa\x6a\x74\x23\xc5\x43\x2e\xad\x82\ +\xa0\x37\x2c\x6c\x25\x0b\x2b\x3c\xea\x88\xed\x6c\x99\x79\x16\xf9\ +\x9c\x13\x9e\x4b\x71\x2f\xcd\x38\x4d\xb3\x5d\x55\xa9\xa6\x2c\xcb\ +\xf4\xc5\xcd\x31\x91\x63\x2a\xdb\xad\x25\x32\x4b\x93\x49\x25\x97\ +\x4f\x3a\x2a\xe5\x93\xd2\x54\xd2\x49\x29\x95\x34\x91\x45\x2a\xb2\ +\x32\x91\x3b\xca\x84\x94\x93\x64\x4e\x8c\xce\x38\xa5\x51\xb5\x33\ +\x36\x17\xb5\xb3\x1a\xb1\x66\xe2\xa2\xd6\x68\xd4\xea\x38\xb2\xcf\ +\x87\x11\xed\x77\x93\xd8\x94\x4e\xb4\xfe\xb9\x31\xd7\xd7\x52\x44\ +\x9f\x79\xc4\xda\x22\x91\x1e\x6c\xe0\x85\x51\xf8\x81\x9f\x44\x69\ +\x11\x59\x8a\xca\x70\x92\x6f\xb1\x5c\xe6\x3e\x02\x94\x7b\xdd\x2d\ +\xfb\xee\x0f\x3e\x8f\xa1\x66\xe0\xf2\xb4\xdc\x37\x7f\xe0\x69\xb8\ +\x86\x3d\x2b\x2a\xea\xc3\x92\x61\x86\x3a\x4e\x60\x3f\x02\x74\x10\ +\xa0\xe0\x4c\x87\x11\x40\x91\xee\x6c\x46\x0a\xef\xde\x55\x32\x53\ +\xe6\x78\x1a\x57\x38\x9b\xe5\x5c\xad\xcf\x96\x7b\x67\xb9\x5a\x3e\ +\xe3\xce\xad\xb0\x92\xda\xf8\x6a\x5e\xb2\xde\xed\x30\xe3\x22\xf7\ +\x29\xcc\x8c\x7b\xd7\x67\x66\xb2\xc1\x7c\x9a\x4a\x32\x65\x74\x40\ +\x19\x6d\xf1\x44\x1c\xdb\x22\x23\xbc\x6e\xd6\x13\xde\xda\xfb\x3f\ +\x76\xfc\xff\x17\ \x00\x00\x10\x85\ \x00\ \x00\xa9\x59\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ @@ -53119,63 +53124,63 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x0a\xf8\x2f\ -\x00\x00\x04\x7c\x00\x00\x00\x00\x00\x01\x00\x0a\x55\x18\ -\x00\x00\x09\x04\x00\x01\x00\x00\x00\x01\x00\x0b\xbc\xa1\ -\x00\x00\x0b\x94\x00\x01\x00\x00\x00\x01\x00\x0c\x98\xac\ -\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x0a\x94\xc3\ -\x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x0b\x15\x79\ -\x00\x00\x08\x2a\x00\x01\x00\x00\x00\x01\x00\x0b\x7e\x27\ -\x00\x00\x0a\xf6\x00\x01\x00\x00\x00\x01\x00\x0c\x6f\x69\ -\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x0b\x3f\x48\ -\x00\x00\x09\x9e\x00\x01\x00\x00\x00\x01\x00\x0b\xfd\x42\ -\x00\x00\x0b\xe4\x00\x01\x00\x00\x00\x01\x00\x0c\xb4\xd0\ -\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x0a\x6e\x3a\ -\x00\x00\x08\x50\x00\x01\x00\x00\x00\x01\x00\x0b\x83\xeb\ -\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x0b\x02\xe3\ -\x00\x00\x04\xe6\x00\x01\x00\x00\x00\x01\x00\x0a\x73\xb9\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x0b\x2e\x3e\ -\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x0a\x63\xce\ -\x00\x00\x0b\x1e\x00\x00\x00\x00\x00\x01\x00\x0c\x7a\xd8\ -\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x0a\x2f\x86\ -\x00\x00\x05\xd6\x00\x01\x00\x00\x00\x01\x00\x0a\xaf\xe2\ -\x00\x00\x0a\xae\x00\x01\x00\x00\x00\x01\x00\x0c\x58\x3a\ -\x00\x00\x0a\xd0\x00\x01\x00\x00\x00\x01\x00\x0c\x65\xd5\ -\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x0a\x9d\xc9\ -\x00\x00\x03\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x27\xcd\ -\x00\x00\x08\xba\x00\x01\x00\x00\x00\x01\x00\x0b\xa5\x77\ -\x00\x00\x09\xf8\x00\x00\x00\x00\x00\x01\x00\x0c\x0d\x8a\ -\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x0a\xc1\x52\ -\x00\x00\x0a\x1c\x00\x00\x00\x00\x00\x01\x00\x0c\x24\x3d\ -\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x0b\x56\xfb\ -\x00\x00\x05\x38\x00\x01\x00\x00\x00\x01\x00\x0a\x83\xb9\ -\x00\x00\x0b\xb4\x00\x00\x00\x00\x00\x01\x00\x0c\xa3\x5a\ -\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xd8\x91\ -\x00\x00\x04\x28\x00\x00\x00\x00\x00\x01\x00\x0a\x37\x8d\ -\x00\x00\x0c\x14\x00\x00\x00\x00\x00\x01\x00\x0c\xc0\xa9\ -\x00\x00\x0a\x64\x00\x00\x00\x00\x00\x01\x00\x0c\x41\xc4\ -\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x0a\x4c\xad\ -\x00\x00\x0a\x8c\x00\x01\x00\x00\x00\x01\x00\x0c\x50\xeb\ -\x00\x00\x09\x26\x00\x01\x00\x00\x00\x01\x00\x0b\xc5\x4a\ -\x00\x00\x0b\x44\x00\x01\x00\x00\x00\x01\x00\x0c\x83\x65\ -\x00\x00\x06\xac\x00\x01\x00\x00\x00\x01\x00\x0a\xea\xd0\ -\x00\x00\x07\xbc\x00\x01\x00\x00\x00\x01\x00\x0b\x4d\x4a\ -\x00\x00\x09\x7c\x00\x00\x00\x00\x00\x01\x00\x0b\xe8\xb1\ -\x00\x00\x05\x5c\x00\x01\x00\x00\x00\x01\x00\x0a\x8a\x82\ -\x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x0b\x68\xb3\ -\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x0a\xbb\xd3\ -\x00\x00\x09\xc8\x00\x01\x00\x00\x00\x01\x00\x0c\x03\xb7\ -\x00\x00\x08\x92\x00\x01\x00\x00\x00\x01\x00\x0b\x9a\x05\ -\x00\x00\x08\xdc\x00\x01\x00\x00\x00\x01\x00\x0b\xac\xcb\ -\x00\x00\x0b\x6a\x00\x01\x00\x00\x00\x01\x00\x0c\x8e\x2a\ -\x00\x00\x0a\x40\x00\x01\x00\x00\x00\x01\x00\x0c\x37\x14\ -\x00\x00\x05\x08\x00\x01\x00\x00\x00\x01\x00\x0a\x7b\x97\ -\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0b\x8a\x33\ -\x00\x00\x06\x58\x00\x00\x00\x00\x00\x01\x00\x0a\xc9\x37\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x0b\x24\xca\ -\x00\x00\x09\x4a\x00\x00\x00\x00\x00\x01\x00\x0b\xcc\x9b\ +\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x0a\xf8\x7b\ +\x00\x00\x04\x7c\x00\x00\x00\x00\x00\x01\x00\x0a\x55\x64\ +\x00\x00\x09\x04\x00\x01\x00\x00\x00\x01\x00\x0b\xbc\xed\ +\x00\x00\x0b\x94\x00\x01\x00\x00\x00\x01\x00\x0c\x98\xf8\ +\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x0a\x95\x0f\ +\x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x0b\x15\xc5\ +\x00\x00\x08\x2a\x00\x01\x00\x00\x00\x01\x00\x0b\x7e\x73\ +\x00\x00\x0a\xf6\x00\x01\x00\x00\x00\x01\x00\x0c\x6f\xb5\ +\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x0b\x3f\x94\ +\x00\x00\x09\x9e\x00\x01\x00\x00\x00\x01\x00\x0b\xfd\x8e\ +\x00\x00\x0b\xe4\x00\x01\x00\x00\x00\x01\x00\x0c\xb5\x1c\ +\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x0a\x6e\x86\ +\x00\x00\x08\x50\x00\x01\x00\x00\x00\x01\x00\x0b\x84\x37\ +\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x0b\x03\x2f\ +\x00\x00\x04\xe6\x00\x01\x00\x00\x00\x01\x00\x0a\x74\x05\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x0b\x2e\x8a\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x0a\x64\x1a\ +\x00\x00\x0b\x1e\x00\x00\x00\x00\x00\x01\x00\x0c\x7b\x24\ +\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x0a\x2f\xd2\ +\x00\x00\x05\xd6\x00\x01\x00\x00\x00\x01\x00\x0a\xb0\x2e\ +\x00\x00\x0a\xae\x00\x01\x00\x00\x00\x01\x00\x0c\x58\x86\ +\x00\x00\x0a\xd0\x00\x01\x00\x00\x00\x01\x00\x0c\x66\x21\ +\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x0a\x9e\x15\ +\x00\x00\x03\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x28\x19\ +\x00\x00\x08\xba\x00\x01\x00\x00\x00\x01\x00\x0b\xa5\xc3\ +\x00\x00\x09\xf8\x00\x00\x00\x00\x00\x01\x00\x0c\x0d\xd6\ +\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x0a\xc1\x9e\ +\x00\x00\x0a\x1c\x00\x00\x00\x00\x00\x01\x00\x0c\x24\x89\ +\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x0b\x57\x47\ +\x00\x00\x05\x38\x00\x01\x00\x00\x00\x01\x00\x0a\x84\x05\ +\x00\x00\x0b\xb4\x00\x00\x00\x00\x00\x01\x00\x0c\xa3\xa6\ +\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xd8\xdd\ +\x00\x00\x04\x28\x00\x00\x00\x00\x00\x01\x00\x0a\x37\xd9\ +\x00\x00\x0c\x14\x00\x00\x00\x00\x00\x01\x00\x0c\xc0\xf5\ +\x00\x00\x0a\x64\x00\x00\x00\x00\x00\x01\x00\x0c\x42\x10\ +\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x0a\x4c\xf9\ +\x00\x00\x0a\x8c\x00\x01\x00\x00\x00\x01\x00\x0c\x51\x37\ +\x00\x00\x09\x26\x00\x01\x00\x00\x00\x01\x00\x0b\xc5\x96\ +\x00\x00\x0b\x44\x00\x01\x00\x00\x00\x01\x00\x0c\x83\xb1\ +\x00\x00\x06\xac\x00\x01\x00\x00\x00\x01\x00\x0a\xeb\x1c\ +\x00\x00\x07\xbc\x00\x01\x00\x00\x00\x01\x00\x0b\x4d\x96\ +\x00\x00\x09\x7c\x00\x00\x00\x00\x00\x01\x00\x0b\xe8\xfd\ +\x00\x00\x05\x5c\x00\x01\x00\x00\x00\x01\x00\x0a\x8a\xce\ +\x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x0b\x68\xff\ +\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x0a\xbc\x1f\ +\x00\x00\x09\xc8\x00\x01\x00\x00\x00\x01\x00\x0c\x04\x03\ +\x00\x00\x08\x92\x00\x01\x00\x00\x00\x01\x00\x0b\x9a\x51\ +\x00\x00\x08\xdc\x00\x01\x00\x00\x00\x01\x00\x0b\xad\x17\ +\x00\x00\x0b\x6a\x00\x01\x00\x00\x00\x01\x00\x0c\x8e\x76\ +\x00\x00\x0a\x40\x00\x01\x00\x00\x00\x01\x00\x0c\x37\x60\ +\x00\x00\x05\x08\x00\x01\x00\x00\x00\x01\x00\x0a\x7b\xe3\ +\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0b\x8a\x7f\ +\x00\x00\x06\x58\x00\x00\x00\x00\x00\x01\x00\x0a\xc9\x83\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x0b\x25\x16\ +\x00\x00\x09\x4a\x00\x00\x00\x00\x00\x01\x00\x0b\xcc\xe7\ \x00\x00\x03\x76\x00\x01\x00\x00\x00\x01\x00\x0a\x0d\xd7\ -\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x0a\x17\x44\ +\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x0a\x17\x90\ " def qInitResources(): diff --git a/src/Mod/Draft/Resources/ui/userprefs-import.ui b/src/Mod/Draft/Resources/ui/userprefs-import.ui index a14084d3b3..95b64c3084 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-import.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-import.ui @@ -280,6 +280,26 @@ If color mapping is choosed, you must choose a color mapping file containing a t + + + + + + If this is checked, the exported objects will be projected to reflect the current view direction + + + Project exported objects along current view direction + + + dxfproject + + + Mod/Draft + + + + + diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 0cb2656ebb..35ef8a2b68 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1190,13 +1190,27 @@ def insert(filename,docname): # EXPORT ######################################################################## +def projectShape(shape,direction): + import Drawing + edges = [] + try: + groups = Drawing.projectEx(shape,direction) + except: + print "unable to project shape" + return shape + else: + for g in groups[0:5]: + if g: + edges.append(g) + return DraftGeomUtils.cleanProjection(Part.makeCompound(edges)) + def getArcData(edge): "returns center, radius, start and end angles of a circle-based edge" ce = edge.Curve.Center radius = edge.Curve.Radius if len(edge.Vertexes) == 1: # closed circle - return ce, radius, 0, 0 + return DraftVecUtils.tup(ce), radius, 0, 0 else: # find direction of arc tang1 = edge.Curve.tangent(edge.ParameterRange[0]) @@ -1218,7 +1232,15 @@ def getArcData(edge): ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce))) ve3 = DraftGeomUtils.findMidpoint(edge) ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce))) + print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3 if (ang3 < ang1) and (ang2 < ang3): + print "inverting, case1" + ang1, ang2 = ang2, ang1 + elif (ang3 > ang1) and (ang3 > ang2): + print "inverting, case2" + ang1, ang2 = ang2, ang1 + elif (ang3 < ang1) and (ang3 < ang2): + print "inverting, case3" ang1, ang2 = ang2, ang1 return DraftVecUtils.tup(ce), radius, ang1, ang2 @@ -1246,6 +1268,7 @@ def getWire(wire,nospline=False): "returns an array of dxf-ready points and bulges from a wire" edges = DraftGeomUtils.sortEdges(wire.Edges) points = [] + # print "processing wire ",wire.Edges for edge in edges: v1 = edge.Vertexes[0].Point if len(edge.Vertexes) < 2: @@ -1256,7 +1279,8 @@ def getWire(wire,nospline=False): c = edge.Curve.Center angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c))) if DraftGeomUtils.isWideAngle(edge): - angle = math.pi*2 - angle + if angle < math.pi: + angle = math.pi*2 - angle # if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))): # angle = -angle # polyline bulge -> negative makes the arc go clockwise @@ -1293,16 +1317,16 @@ def getWire(wire,nospline=False): # print "wire verts: ",points return points -def getBlock(obj): +def getBlock(sh,obj): "returns a dxf block with the contents of the object" block = dxfLibrary.Block(name=obj.Name,layer=getGroup(obj,exportList)) - writeShape(obj,block) + writeShape(sh,obj,block) return block -def writeShape(ob,dxfobject,nospline=False): +def writeShape(sh,ob,dxfobject,nospline=False): "writes the object's shape contents in the given dxf object" processededges = [] - for wire in ob.Shape.Wires: # polylines + for wire in sh.Wires: # polylines for e in wire.Edges: processededges.append(e.hashCode()) if (len(wire.Edges) == 1) and (DraftGeomUtils.geomType(wire.Edges[0]) == "Circle"): @@ -1319,22 +1343,32 @@ def writeShape(ob,dxfobject,nospline=False): dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0], int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob), layer=getGroup(ob,exportList))) - if len(processededges) < len(ob.Shape.Edges): # lone edges + if len(processededges) < len(sh.Edges): # lone edges loneedges = [] - for e in ob.Shape.Edges: + for e in sh.Edges: if not(e.hashCode() in processededges): loneedges.append(e) # print "lone edges ",loneedges for edge in loneedges: if (DraftGeomUtils.geomType(edge) == "BSplineCurve") and ((not nospline) or (len(edge.Vertexes) == 1)): # splines - points = [] - spline = getSplineSegs(edge) - for p in spline: - points.append((p.x,p.y,p.z,None,None,0.0)) - dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0], - 0, color=getACI(ob), - layer=getGroup(ob,exportList))) + if (len(edge.Vertexes) == 1) and (edge.Curve.isClosed()): + # special case: 1-vert closed spline, approximate as a circle + c = DraftGeomUtils.getCircleFromSpline(edge) + if c: + dxfobject.append(dxfLibrary.Circle(DraftVecUtils.tup(c.Curve.Center), c.Curve.Radius, + color=getACI(ob), + layer=getGroup(ob,exportList))) + else: + points = [] + spline = getSplineSegs(edge) + for p in spline: + points.append((p.x,p.y,p.z,None,None,0.0)) + dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0], + 0, color=getACI(ob), + layer=getGroup(ob,exportList))) elif DraftGeomUtils.geomType(edge) == "Circle": # curves center, radius, ang1, ang2 = getArcData(edge) + if not isinstance(center,tuple): + center = DraftVecUtils.tup(center) if len(edge.Vertexes) == 1: # circles dxfobject.append(dxfLibrary.Circle(center, radius, color=getACI(ob), @@ -1389,27 +1423,37 @@ def export(objectslist,filename,nospline=False): for ob in exportList: print "processing ",ob.Name if ob.isDerivedFrom("Part::Feature"): - if not ob.Shape.isNull(): - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"): + if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"): + sh = None + if not ob.Shape.isNull(): writeMesh(ob,dxf) + elif FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfproject"): + direction = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + sh = projectShape(ob.Shape,direction) + else: + if ob.Shape.Volume > 0: + sh = projectShape(ob.Shape,Vector(0,0,1)) else: - if ob.Shape.ShapeType == 'Compound': - if (len(ob.Shape.Wires) == 1): + sh = ob.Shape + if sh: + if not sh.isNull(): + if sh.ShapeType == 'Compound': + if (len(sh.Wires) == 1): # only one wire in this compound, no lone edge -> polyline - if (len(ob.Shape.Wires[0].Edges) == len(ob.Shape.Edges)): - writeShape(ob,dxf,nospline) + if (len(sh.Wires[0].Edges) == len(sh.Edges)): + writeShape(sh,ob,dxf,nospline) else: # 1 wire + lone edges -> block - block = getBlock(ob) + block = getBlock(sh,ob) dxf.blocks.append(block) dxf.append(dxfLibrary.Insert(name=ob.Name.upper())) else: # all other cases: block - block = getBlock(ob) + block = getBlock(sh,ob) dxf.blocks.append(block) dxf.append(dxfLibrary.Insert(name=ob.Name.upper())) else: - writeShape(ob,dxf,nospline) + writeShape(sh,ob,dxf,nospline) elif Draft.getType(ob) == "Annotation": # texts From b8b8f6c460e6a1d2630d3ab6bc88d23ca42c1e1d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 12 Apr 2013 15:37:10 -0300 Subject: [PATCH 10/53] Arch: WebGL exporter now has mouse controls --- src/Mod/Arch/importWebGL.py | 99 ++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py index dbb49b7d9c..6a28308487 100644 --- a/src/Mod/Arch/importWebGL.py +++ b/src/Mod/Arch/importWebGL.py @@ -25,19 +25,14 @@ import FreeCAD,FreeCADGui,Arch,Draft from DraftTools import translate tab = " " +addWireframe = False if open.__module__ == '__builtin__': pythonopen = open def export(exportList,filename): "exports the given objects to a .html file" - - # get three.min.js - threejspath = Arch.download("https://raw.github.com/mrdoob/three.js/master/build/three.min.js") - threejsfile = pythonopen(threejspath,"r") - threeminjs = threejsfile.read() - threejsfile.close() - + # get objects data objectsData = '' for obj in exportList: @@ -45,7 +40,6 @@ def export(exportList,filename): # build the final file template = getTemplate() - template = template.replace("$ThreeMinJs",threeminjs) template = template.replace("$CameraData",getCameraData()) template = template.replace("$ObjectsData",objectsData) template = template.replace("$TestData",getTestData()) @@ -80,8 +74,11 @@ def getCameraData(): def getObjectData(obj): "returns the geometry data of an object as three.js snippet" + + result = "" if obj.isDerivedFrom("Part::Feature"): + fcmesh = obj.Shape.tessellate(0.1) result = "var geom = new THREE.Geometry();\n" @@ -96,21 +93,9 @@ def getObjectData(obj): # adding facets data for f in fcmesh[1]: result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n" - - # adding material - col = obj.ViewObject.ShapeColor - rgb = Draft.getrgb(col,testbw=False) - #rgb = "#888888" # test color - result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" - - # adding the mesh to the scene - result += tab+"var mesh = new THREE.Mesh( geom, material );\n" - result += tab+"scene.add( mesh );\n"+tab - - # print result - return result - + elif obj.isDerivedFrom("Mesh::Feature"): + mesh = obj.Mesh result = "var geom = new THREE.Geometry();\n" @@ -126,21 +111,26 @@ def getObjectData(obj): # adding facets data for f in mesh.Facets: result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n" + + if result: - # adding material + # adding a base material col = obj.ViewObject.ShapeColor rgb = Draft.getrgb(col,testbw=False) #rgb = "#888888" # test color - result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + + # adding a wireframe material + result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: " + result += "0x000000, wireframe: true, transparent: true } );\n" + result += tab+"var material = [ basematerial, wireframe ];\n" # adding the mesh to the scene - result += tab+"var mesh = new THREE.Mesh( geom, material );\n" + #result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n" + result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n" result += tab+"scene.add( mesh );\n"+tab - # print result - return result - - return "" + return result def getTestData(): "returns a simple cube as three.js snippet" @@ -158,26 +148,42 @@ def getTemplate(): result = """ - FreeCAD model - + FreeCAD model + From 80ed02054edd0f15fe739d00ecd74b462be6c867 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 13 Apr 2013 00:29:05 -0300 Subject: [PATCH 11/53] Arch: Simplified webgl exporter --- src/Mod/Arch/importWebGL.py | 89 +++++++++++++++---------------------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py index 6a28308487..36bd3e3321 100644 --- a/src/Mod/Arch/importWebGL.py +++ b/src/Mod/Arch/importWebGL.py @@ -21,9 +21,16 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Arch,Draft +"FreeCAD webgl exporter" + +import FreeCAD,Draft from DraftTools import translate +if FreeCAD.GuiUp: + import FreeCADGui +else: + FreeCADGui = None + tab = " " addWireframe = False @@ -33,42 +40,38 @@ if open.__module__ == '__builtin__': def export(exportList,filename): "exports the given objects to a .html file" + html = getHTML(exportList) + outfile = pythonopen(filename,"wb") + outfile.write(html) + outfile.close() + FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename) + +def getHTML(objectsList): + "returns the complete HTML code of a viewer for the given objects" + # get objects data objectsData = '' - for obj in exportList: + for obj in objectsList: objectsData += getObjectData(obj) - - # build the final file template = getTemplate() template = template.replace("$CameraData",getCameraData()) template = template.replace("$ObjectsData",objectsData) - template = template.replace("$TestData",getTestData()) - outfile = pythonopen(filename,"wb") - outfile.write(template) - outfile.close() - FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename) + return template def getCameraData(): "returns the position and direction of the camera as three.js snippet" - # getting camera position - pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base - #result = "camera.position.set( -10,5,15" # test position - result = "camera.position.set( " - result += str(pos.x) + ", " - result += str(pos.y) + ", " - result += str(pos.z) - - # getting camera lookat vector - lookat = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() - lookat = pos.add(lookat) - result += " );\n"+tab+"camera.lookAt( scene.position );\n"+tab - #result += " );\n"+tab+"camera.lookAt( " - #result += str(lookat.x) + ", " - #result += str(lookat.y) + ", " - #result += str(lookat.z) - #result += " );\n"+tab - + result = "" + if FreeCADGui: + # getting camera position + pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base + result += "camera.position.set( " + result += str(pos.x) + ", " + result += str(pos.y) + ", " + result += str(pos.z) + " );\n" + else: + result += "camera.position.set(0,0,1000);\n" + result += tab+"camera.lookAt( scene.position );\n"+tab # print result return result @@ -76,12 +79,9 @@ def getObjectData(obj): "returns the geometry data of an object as three.js snippet" result = "" - if obj.isDerivedFrom("Part::Feature"): - fcmesh = obj.Shape.tessellate(0.1) result = "var geom = new THREE.Geometry();\n" - # adding vertices data for i in range(len(fcmesh[0])): v = fcmesh[0][i] @@ -89,16 +89,13 @@ def getObjectData(obj): result += tab+"console.log(geom.vertices)\n" for i in range(len(fcmesh[0])): result += tab+"geom.vertices.push(v"+str(i)+");\n" - # adding facets data for f in fcmesh[1]: result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n" elif obj.isDerivedFrom("Mesh::Feature"): - mesh = obj.Mesh result = "var geom = new THREE.Geometry();\n" - # adding vertices data for p in mesh.Points: v = p.Vector @@ -107,41 +104,29 @@ def getObjectData(obj): result += tab+"console.log(geom.vertices)\n" for p in mesh.Points: result += tab+"geom.vertices.push(v"+str(p.Index)+");\n" - # adding facets data for f in mesh.Facets: result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n" if result: - # adding a base material - col = obj.ViewObject.ShapeColor - rgb = Draft.getrgb(col,testbw=False) - #rgb = "#888888" # test color + if FreeCADGui: + col = obj.ViewObject.ShapeColor + rgb = Draft.getrgb(col,testbw=False) + else: + rgb = "#888888" # test color result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" - # adding a wireframe material result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: " result += "0x000000, wireframe: true, transparent: true } );\n" result += tab+"var material = [ basematerial, wireframe ];\n" - # adding the mesh to the scene #result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n" result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n" result += tab+"scene.add( mesh );\n"+tab return result - -def getTestData(): - "returns a simple cube as three.js snippet" - - #return """var geometry = new THREE.CubeGeometry( .5, .5, .5 ); - # var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } ); - # var mesh = new THREE.Mesh( geometry, material ); - # scene.add( mesh );""" - - return "" - + def getTemplate(): "returns a html template" @@ -183,8 +168,6 @@ def getTemplate(): controls.staticMoving = true; controls.dynamicDampingFactor = 0.3; controls.keys = [ 65, 83, 68 ]; - - $TestData // placeholder for a test cube $ObjectsData // placeholder for the FreeCAD objects From 60a12031cb661cdd7a70b0a02516c63fff8036f2 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 13 Apr 2013 18:57:35 -0300 Subject: [PATCH 12/53] Arch: Better wireframe material for the webgl exporter --- src/Mod/Arch/importWebGL.py | 56 ++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/Mod/Arch/importWebGL.py b/src/Mod/Arch/importWebGL.py index 36bd3e3321..1e5d76858e 100644 --- a/src/Mod/Arch/importWebGL.py +++ b/src/Mod/Arch/importWebGL.py @@ -23,7 +23,7 @@ "FreeCAD webgl exporter" -import FreeCAD,Draft +import FreeCAD,Draft,Part,DraftGeomUtils from DraftTools import translate if FreeCAD.GuiUp: @@ -75,10 +75,13 @@ def getCameraData(): # print result return result -def getObjectData(obj): - "returns the geometry data of an object as three.js snippet" +def getObjectData(obj,wireframeMode="faceloop"): + """returns the geometry data of an object as three.js snippet. wireframeMode + can be multimaterial, faceloop or None""" result = "" + wires = [] + if obj.isDerivedFrom("Part::Feature"): fcmesh = obj.Shape.tessellate(0.1) result = "var geom = new THREE.Geometry();\n" @@ -92,7 +95,15 @@ def getObjectData(obj): # adding facets data for f in fcmesh[1]: result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n" - + for f in obj.Shape.Faces: + for w in f.Wires: + wo = Part.Wire(DraftGeomUtils.sortEdges(w.Edges)) + p = [] + for v in wo.Vertexes: + p.append(v.Point) + p.append(wo.Vertexes[0].Point) + wires.append(p) + elif obj.isDerivedFrom("Mesh::Feature"): mesh = obj.Mesh result = "var geom = new THREE.Geometry();\n" @@ -116,14 +127,33 @@ def getObjectData(obj): else: rgb = "#888888" # test color result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" - # adding a wireframe material - result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: " - result += "0x000000, wireframe: true, transparent: true } );\n" - result += tab+"var material = [ basematerial, wireframe ];\n" - # adding the mesh to the scene - #result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n" - result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n" - result += tab+"scene.add( mesh );\n"+tab + #result += tab+"var basematerial = new THREE.MeshLambertMaterial( { color: 0x"+str(rgb)[1:]+" } );\n" + + if wireframeMode == "faceloop": + # adding the mesh to the scene with a wireframe copy + result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n" + result += tab+"scene.add( mesh );\n" + result += tab+"var linematerial = new THREE.LineBasicMaterial({color: 0x000000,});\n" + for w in wires: + result += tab+"var wire = new THREE.Geometry();\n" + for p in w: + result += tab+"wire.vertices.push(new THREE.Vector3(" + result += str(p.x)+", "+str(p.y)+", "+str(p.z)+"));\n" + result += tab+"var line = new THREE.Line(wire, linematerial);\n" + result += tab+"scene.add(line);\n" + + elif wireframeMode == "multimaterial": + # adding a wireframe material + result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: " + result += "0x000000, wireframe: true, transparent: true } );\n" + result += tab+"var material = [ basematerial, wireframe ];\n" + result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n" + result += tab+"scene.add( mesh );\n"+tab + + else: + # adding the mesh to the scene with simple material + result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n" + result += tab+"scene.add( mesh );\n"+tab return result @@ -172,7 +202,7 @@ def getTemplate(): $ObjectsData // placeholder for the FreeCAD objects var light = new THREE.PointLight( 0xFFFF00 ); - light.position.set( -10, -10, 10 ); + light.position.set( -10000, -10000, 10000 ); scene.add( light ); renderer.render( scene, camera ); From ba70d096d0b8a42fb46b7af8732ae8940e70d37d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 14 Apr 2013 17:45:00 -0300 Subject: [PATCH 13/53] 0001003: Interactive Arch Structure tool --- src/Mod/Arch/ArchStructure.py | 95 +++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 7b6c5ff6a1..14a9a3f80d 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -68,10 +68,19 @@ class _CommandStructure: 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Structure","Creates a structure object from scratch or from a selected object (sketch, wire, face or solid)")} def Activated(self): - FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure"))) - FreeCADGui.doCommand("import Arch") + + global QtGui, QtCore + from PyQt4 import QtGui, QtCore + + self.Length = 0.5 + self.Width = 0.2 + self.Height = 1 + self.continueCmd = False sel = FreeCADGui.Selection.getSelection() if sel: + # direct creation + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure"))) + FreeCADGui.doCommand("import Arch") # if selection contains structs and axes, make a system st = Draft.getObjectsOfType(sel,"Structure") ax = Draft.getObjectsOfType(sel,"Axis") @@ -81,10 +90,90 @@ class _CommandStructure: # else, do normal structs for obj in sel: FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")") + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() else: - FreeCADGui.doCommand("Arch.makeStructure()") + # interactive mode + import DraftTrackers + self.points = [] + self.tracker = DraftTrackers.boxTracker() + self.tracker.on() + FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox()) + + def getPoint(self,point=None,obj=None): + "this function is called by the snapper when it has a 3D point" + self.tracker.finalize() + if point == None: + return + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure"))) + FreeCADGui.doCommand('import Arch') + FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')') + FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point)) FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() + if self.continueCmd: + self.Activated() + + def taskbox(self): + "sets up a taskbox widget" + w = QtGui.QWidget() + w.setWindowTitle(str(translate("Arch","Structure options"))) + lay0 = QtGui.QVBoxLayout(w) + + lay1 = QtGui.QHBoxLayout() + lay0.addLayout(lay1) + label1 = QtGui.QLabel(str(translate("Arch","Length"))) + lay1.addWidget(label1) + value1 = QtGui.QDoubleSpinBox() + value1.setDecimals(2) + value1.setValue(self.Length) + lay1.addWidget(value1) + + lay2 = QtGui.QHBoxLayout() + lay0.addLayout(lay2) + label2 = QtGui.QLabel(str(translate("Arch","Width"))) + lay2.addWidget(label2) + value2 = QtGui.QDoubleSpinBox() + value2.setDecimals(2) + value2.setValue(self.Width) + lay2.addWidget(value2) + + lay3 = QtGui.QHBoxLayout() + lay0.addLayout(lay3) + label3 = QtGui.QLabel(str(translate("Arch","Height"))) + lay3.addWidget(label3) + value3 = QtGui.QDoubleSpinBox() + value3.setDecimals(2) + value3.setValue(self.Height) + lay3.addWidget(value3) + + value4 = QtGui.QCheckBox(str(translate("Arch","Continue"))) + lay0.addWidget(value4) + + QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setLength) + QtCore.QObject.connect(value2,QtCore.SIGNAL("valueChanged(double)"),self.setWidth) + QtCore.QObject.connect(value3,QtCore.SIGNAL("valueChanged(double)"),self.setHeight) + QtCore.QObject.connect(value4,QtCore.SIGNAL("stateChanged(int)"),self.setContinue) + return w + + def update(self,point): + "this function is called by the Snapper when the mouse is moved" + self.tracker.pos(point) + + def setWidth(self,d): + self.Width = d + self.tracker.width(d) + + def setHeight(self,d): + self.Height = d + self.tracker.height(d) + + def setLength(self,d): + self.Length = d + self.tracker.length(d) + + def setContinue(self,i): + self.continueCmd = bool(i) class _Structure(ArchComponent.Component): "The Structure object" From 811e9c09b4358835b7f4f3bc28f2e9f11f4c3460 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 15 Apr 2013 11:29:45 -0300 Subject: [PATCH 14/53] Included more modules in sphinx docs --- src/Doc/sphinx/Document.rst | 5 +- src/Doc/sphinx/DocumentObject.rst | 18 +++++++ src/Doc/sphinx/FreeCAD.rst | 9 ---- src/Doc/sphinx/Matrix.rst | 10 ++++ src/Doc/sphinx/Placement.rst | 10 ++++ src/Doc/sphinx/Vector.rst | 10 ++++ src/Doc/sphinx/ViewProvider.rst | 10 ++++ src/Doc/sphinx/conf.py | 6 ++- src/Doc/sphinx/index.rst | 5 ++ src/Mod/TemplatePyMod/DocumentObject.py | 71 +++++++++++++++++++++++++ 10 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 src/Doc/sphinx/DocumentObject.rst create mode 100644 src/Doc/sphinx/Matrix.rst create mode 100644 src/Doc/sphinx/Placement.rst create mode 100644 src/Doc/sphinx/Vector.rst create mode 100644 src/Doc/sphinx/ViewProvider.rst diff --git a/src/Doc/sphinx/Document.rst b/src/Doc/sphinx/Document.rst index 3e82c8379e..2b8a9d3650 100644 --- a/src/Doc/sphinx/Document.rst +++ b/src/Doc/sphinx/Document.rst @@ -4,5 +4,6 @@ The FreeCAD Document .. toctree:: :maxdepth: 4 -.. automodule:: ActiveDocument - :members: +.. automodule:: DocumentObject + + diff --git a/src/Doc/sphinx/DocumentObject.rst b/src/Doc/sphinx/DocumentObject.rst new file mode 100644 index 0000000000..c329182214 --- /dev/null +++ b/src/Doc/sphinx/DocumentObject.rst @@ -0,0 +1,18 @@ +The FreeCAD Document Object +=========================== + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DocumentObject + + .. autoclass:: DocumentObject + :members: + + .. method:: __setstate__(value) + + allows to save custom attributes of this object as strings, so they can be saved when saving the FreeCAD document + + .. method:: __getstate__() + + reads values previously saved with __setstate__() diff --git a/src/Doc/sphinx/FreeCAD.rst b/src/Doc/sphinx/FreeCAD.rst index eff8e09cfe..1a280b6d53 100644 --- a/src/Doc/sphinx/FreeCAD.rst +++ b/src/Doc/sphinx/FreeCAD.rst @@ -7,14 +7,5 @@ The FreeCAD module .. automodule:: FreeCAD :members: - .. autoclass:: Vector - :members: - - .. autoclass:: Matrix - :members: - - .. autoclass:: Placement - :members: - .. autoclass:: Console :members: diff --git a/src/Doc/sphinx/Matrix.rst b/src/Doc/sphinx/Matrix.rst new file mode 100644 index 0000000000..90e4e8ba3f --- /dev/null +++ b/src/Doc/sphinx/Matrix.rst @@ -0,0 +1,10 @@ +The Matrix object +================= + +.. toctree:: + :maxdepth: 4 + +.. automodule:: FreeCAD + + .. autoclass:: Matrix + :members: diff --git a/src/Doc/sphinx/Placement.rst b/src/Doc/sphinx/Placement.rst new file mode 100644 index 0000000000..56d596e981 --- /dev/null +++ b/src/Doc/sphinx/Placement.rst @@ -0,0 +1,10 @@ +The Placement object +==================== + +.. toctree:: + :maxdepth: 4 + +.. automodule:: FreeCAD + + .. autoclass:: Placement + :members: diff --git a/src/Doc/sphinx/Vector.rst b/src/Doc/sphinx/Vector.rst new file mode 100644 index 0000000000..f7b8d9287b --- /dev/null +++ b/src/Doc/sphinx/Vector.rst @@ -0,0 +1,10 @@ +The Vector object +================= + +.. toctree:: + :maxdepth: 4 + +.. automodule:: FreeCAD + + .. autoclass:: Vector + :members: diff --git a/src/Doc/sphinx/ViewProvider.rst b/src/Doc/sphinx/ViewProvider.rst new file mode 100644 index 0000000000..675dbce697 --- /dev/null +++ b/src/Doc/sphinx/ViewProvider.rst @@ -0,0 +1,10 @@ +The View Provider object +======================== + +.. toctree:: + :maxdepth: 4 + +.. automodule:: DocumentObject + + .. autoclass:: ViewProvider + :members: diff --git a/src/Doc/sphinx/conf.py b/src/Doc/sphinx/conf.py index 77e697346e..52c32f05d0 100644 --- a/src/Doc/sphinx/conf.py +++ b/src/Doc/sphinx/conf.py @@ -53,9 +53,13 @@ elif commands.getstatusoutput("locate FreeCAD/lib")[0] == 0: path = commands.getstatusoutput("locate FreeCAD/lib")[1].split()[0] sys.path.append(path) +# locate TemplatePyMod +if commands.getstatusoutput("locate TemplatePyMod")[0] == 0: + path = commands.getstatusoutput("locate TemplatePyMod")[1].split()[0] + sys.path.append(path) + import FreeCAD, FreeCADGui FreeCADGui.showMainWindow() # this is needed for complete import of GUI modules -from FreeCAD import Document # -- General configuration ----------------------------------------------------- diff --git a/src/Doc/sphinx/index.rst b/src/Doc/sphinx/index.rst index c4004f32ef..ff12b26347 100644 --- a/src/Doc/sphinx/index.rst +++ b/src/Doc/sphinx/index.rst @@ -13,7 +13,12 @@ This is the complete python API reference of the FreeCAD appication FreeCAD.rst FreeCADGui.rst + Vector.rst + Placement.rst + Matrix.rst Document.rst + DocumentObject.rst + ViewProvider.rst Mesh.rst Part.rst Sketch.rst diff --git a/src/Mod/TemplatePyMod/DocumentObject.py b/src/Mod/TemplatePyMod/DocumentObject.py index fd27737f2a..25785aec07 100644 --- a/src/Mod/TemplatePyMod/DocumentObject.py +++ b/src/Mod/TemplatePyMod/DocumentObject.py @@ -2,9 +2,20 @@ # (c) 2011 Werner Mayer LGPL class DocumentObject(object): + """The Document object is the base class for all FreeCAD objects. + Example of use: + + import FreeCAD + + doc=FreeCAD.newDocument() + + myobj = doc.addObject("Mesh::FeaturePython","MyName") + + myobj.addProperty("App::PropertyLinkList","Layers","Base", "Layers")""" def __init__(self): self.__object__=None def execute(self): + "this method is executed on object creation and whenever the document is recomputed" raise Exception("Not yet implemented") #def onChanged(self,prop): # return None @@ -14,67 +25,98 @@ class DocumentObject(object): # else: # return object.__getattribute__(self,attr) def addProperty(self,type,name='',group='',doc='',attr=0,readonly=False,hidden=False): + "adds a new property to this object" self.__object__.addProperty(type,name,group,doc,attr,readonly,hidden) def supportedProperties(self): + "lists the property types supported by this object" return self.__object__.supportedProperties() def isDerivedFrom(self, obj): + """returns True if this object is derived from the given C++ class, for + example Part::Feature""" return self.__object__.isDerivedFrom(obj) def getAllDerivedFrom(self): + "returns all parent C++ classes of this object" return self.__object__.getAllDerivedFrom() def getProperty(self,attr): + "returns the value of a given property" return self.__object__.getPropertyByName(attr) def getTypeOfProperty(self,attr): + "returns the type of a given property" return self.__object__.getTypeOfProperty(attr) def getGroupOfProperty(self,attr): + "returns the group of a given property" return self.__object__.getGroupOfProperty(attr) def getDocumentationOfProperty(self,attr): + "returns the documentation string of a given property" return self.__object__.getDocumentationOfProperty(attr) def touch(self): + "marks this object to be recomputed" return self.__object__.touch() def purgeTouched(self): + "removes the to-be-recomputed flag of this object" return self.__object__.purgeTouched() def __setstate__(self,value): + """allows to save custom attributes of this object as strings, so + they can be saved when saving the FreeCAD document""" return None def __getstate__(self): + """reads values previously saved with __setstate__()""" return None @property def PropertiesList(self): + "lists the current properties of this object" return self.__object__.PropertiesList @property def Type(self): + "shows the C++ class of this object" return self.__object__.Type @property def Module(self): + "gives the module this object is defined in" return self.__object__.Module @property def Content(self): + """shows the contents of the properties of this object as an xml string. + This is the content that is saved when the file is saved by FreeCAD""" return self.__object__.Content @property def MemSize(self): + "shows the amount of memory this object uses" return self.__object__.MemSize @property def Name(self): + "the name ofthis object, unique in the FreeCAD document" return self.__object__.Name @property def Document(self): + "the document this object is part of" return self.__object__.Document @property def State(self): + "shows if this object is valid (presents no errors)" return self.__object__.State @property def ViewObject(self): return self.__object__.ViewObject @ViewObject.setter def ViewObject(self,value): + """returns or sets the ViewObject associated with this object. Returns + None if FreeCAD is running in console mode""" self.__object__.ViewObject=value @property def InList(self): + "lists the parents of this object" return self.__object__.InList @property def OutList(self): + "lists the children of this object" return self.__object__.OutList class ViewProvider(object): + """The ViewProvider is the counterpart of the DocumentObject in + the GUI space. It is only present when FreeCAD runs in GUI mode. + It contains all that is needed to represent the DocumentObject in + the 3D view and the FreeCAD interface""" def __init__(self): self.__vobject__=None #def getIcon(self): @@ -92,6 +134,7 @@ class ViewProvider(object): #def onChanged(self, prop): # return None def addDisplayMode(self,node,mode): + "adds a coin node as a display mode to this object" self.__vobject__.addDisplayMode(node,mode) #def getDefaultDisplayMode(self): # return "" @@ -100,65 +143,93 @@ class ViewProvider(object): #def setDisplayMode(self,mode): # return mode def addProperty(self,type,name='',group='',doc='',attr=0,readonly=False,hidden=False): + "adds a new property to this object" self.__vobject__.addProperty(type,name,group,doc,attr,readonly,hidden) def update(self): + "this method is executed whenever any of the properties of this ViewProvider changes" self.__vobject__.update() def show(self): + "switches this object to visible" self.__vobject__.show() def hide(self): + "switches this object to invisible" self.__vobject__.hide() def isVisible(self): + "shows wether this object is visible or invisible" return self.__vobject__.isVisible() def toString(self): + "returns a string representation of the coin node of this object" return self.__vobject__.toString() def startEditing(self,mode=0): + "sets this object in edit mode" return self.__vobject__.startEditing(mode) def finishEditing(self): + "leaves edit mode for this object" self.__vobject__.finishEditing() def isEditing(self): + "shows wether this object is in edit mode" self.__vobject__.isEditing() def setTransformation(self,trsf): + "defines a transformation for this object" return self.__vobject__.setTransformation(trsf) def supportedProperties(self): + "lists the property types this ViewProvider supports" return self.__vobject__.supportedProperties() def isDerivedFrom(self, obj): + """returns True if this object is derived from the given C++ class, for + example Part::Feature""" return self.__vobject__.isDerivedFrom(obj) def getAllDerivedFrom(self): + "returns all parent C++ classes of this object" return self.__vobject__.getAllDerivedFrom() def getProperty(self,attr): + "returns the value of a given property" return self.__vobject__.getPropertyByName(attr) def getTypeOfProperty(self,attr): + "returns the type of a given property" return self.__vobject__.getTypeOfProperty(attr) def getGroupOfProperty(self,attr): + "returns the group of a given property" return self.__vobject__.getGroupOfProperty(attr) def getDocumentationOfProperty(self,attr): + "returns the documentation string of a given property" return self.__vobject__.getDocumentationOfProperty(attr) @property def Annotation(self): + "returns the Annotation coin node of this object" return self.__vobject__.Annotation @property def RootNode(self): + "returns the Root coin node of this object" return self.__vobject__.RootNode @property def DisplayModes(self): + "lists the display modes of this object" return self.__vobject__.listDisplayModes() @property def PropertiesList(self): + "lists the current properties of this object" return self.__vobject__.PropertiesList @property def Type(self): + "shows the C++ class of this object" return self.__vobject__.Type @property def Module(self): + "gives the module this object is defined in" return self.__vobject__.Module @property def Content(self): + """shows the contents of the properties of this object as an xml string. + This is the content that is saved when the file is saved by FreeCAD""" return self.__vobject__.Content @property def MemSize(self): + "shows the amount of memory this object uses" return self.__vobject__.MemSize @property def Object(self): + "returns the DocumentObject this ViewProvider is associated to" return self.__vobject__.Object From d921c9124bc1a83a184e16af568d3e0abdd8aa7a Mon Sep 17 00:00:00 2001 From: WandererFan Date: Mon, 15 Apr 2013 13:25:25 -0400 Subject: [PATCH 15/53] Add Draft.ShapeString Gui tool and makeShapeString function --- src/Mod/Draft/Draft.py | 120 ++- src/Mod/Draft/DraftGui.py | 206 ++++- src/Mod/Draft/DraftTools.py | 113 +++ src/Mod/Draft/Draft_rc.py | 875 ++++++++++++------ src/Mod/Draft/InitGui.py | 3 +- src/Mod/Draft/Resources/Draft.qrc | 1 + .../Resources/icons/Draft_ShapeString.svg | 112 +++ src/Mod/Draft/Resources/ui/userprefs-base.ui | 47 +- 8 files changed, 1157 insertions(+), 320 deletions(-) create mode 100644 src/Mod/Draft/Resources/icons/Draft_ShapeString.svg diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 296ea3f6a2..8cf610d06f 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -101,7 +101,7 @@ def getParamType(param): "modalt"]: return "int" elif param in ["constructiongroupname","textfont","patternFile","template","maxSnapEdges", - "snapModes"]: + "snapModes","FontFile"]: return "string" elif param in ["textheight","tolerance","gridSpacing"]: return "float" @@ -142,6 +142,11 @@ def precision(): def tolerance(): "tolerance(): returns the tolerance value from Draft user settings" return getParam("tolerance") + +def epsilon(): + ''' epsilon(): returns a small number based on Draft.tolerance() for use in + floating point comparisons. Use with caution. ''' + return (1.0/(10.0**tolerance())) def getRealName(name): "getRealName(string): strips the trailing numbers from a string name" @@ -1682,6 +1687,34 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5): FreeCAD.ActiveDocument.recompute() return obj +def makeShapeString(String,FontFile,Size = 100,Tracking = 0): + '''ShapeString(Text,FontFile,Height,Track): Turns a text string + into a Compound Shape''' + + # temporary code + import platform + if not (platform.system() == 'Linux'): +# if (platform.system() == 'Linux'): + FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet implemented for your platform.\n") + return (None) + # temporary code + + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","ShapeString") + _ShapeString(obj) + obj.String = String + obj.FontFile = FontFile + obj.Size = Size + obj.Tracking = Tracking + + if gui: + _ViewProviderDraft(obj.ViewObject) + formatObject(obj) + obrep = obj.ViewObject + if "PointSize" in obrep.PropertiesList: obrep.PointSize = 1 # hide the segment end points + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj + def clone(obj,delta=None): '''clone(obj,[delta]): makes a clone of the given object(s). The clone is an exact, linked copy of the given object. If the original object changes, the final object @@ -3657,6 +3690,91 @@ class _ViewProviderClone(_ViewProviderDraftAlt): def getIcon(self): return ":/icons/Draft_Clone.svg" + +class _ShapeString(_DraftObject): + "The ShapeString object" + + def __init__(self, obj): + _DraftObject.__init__(self,obj,"ShapeString") + obj.addProperty("App::PropertyString","String","Base","Text string") + obj.addProperty("App::PropertyString","FontFile","Base","Font file name") + obj.addProperty("App::PropertyFloat","Size","Base","Height of text") + obj.addProperty("App::PropertyInteger","Tracking","Base", + "Inter-character spacing") + + def execute(self, fp): + self.createGeometry(fp) + + def onChanged(self, fp, prop): + pass + + def createGeometry(self,fp): + import Part +# import OpenSCAD2Dgeom + import os + if fp.String and fp.FontFile: + if fp.Placement: + plm = fp.Placement + # TODO: os.path.splitunc() for Win/Samba net files? + head, tail = os.path.splitdrive(fp.FontFile) # os.path.splitdrive() for Win + head, tail = os.path.split(tail) + head = head + '/' # os.split drops last '/' from head + CharList = Part.makeWireString(fp.String, + head, + tail, + fp.Size, + fp.Tracking) + SSChars = [] + for char in CharList: + CharFaces = [] + for CWire in char: + f = Part.Face(CWire) + if f: + CharFaces.append(f) + # whitespace (ex: ' ') has no faces. This breaks OpenSCAD2Dgeom... + if CharFaces: +# s = OpenSCAD2Dgeom.Overlappingfaces(CharFaces).makeshape() + s = self.makeGlyph(CharFaces) + SSChars.append(s) + shape = Part.Compound(SSChars) + fp.Shape = shape + if plm: + fp.Placement = plm + + def makeGlyph(self, facelist): + ''' turn list of simple contour faces into a compound shape representing a glyph ''' + ''' remove cuts, fuse overlapping contours, retain islands ''' + import Part + if len(facelist) == 1: + return(facelist[0]) + + sortedfaces = sorted(facelist,key=(lambda shape: shape.Area),reverse=True) + + biggest = sortedfaces[0] + result = biggest + islands =[] + for face in sortedfaces[1:]: + bcfA = biggest.common(face).Area + fA = face.Area + difA = abs(bcfA - fA) + eps = epsilon() +# if biggest.common(face).Area == face.Area: + if difA <= eps: # close enough to zero + # biggest completely overlaps current face ==> cut + result = result.cut(face) +# elif biggest.common(face).Area == 0: + elif bcfA <= eps: + # island + islands.append(face) + else: + # partial overlap - (font designer error?) + result = result.fuse(face) + glyphfaces = [result] + glyphfaces.extend(islands) + ret = Part.Compound(glyphfaces) # should we fuse these instead of making compound? + return ret + +#----End of Python Features Definitions----# if gui: if not hasattr(FreeCADGui,"Snapper"): diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 3352f05128..1ea342253e 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -313,8 +313,29 @@ class DraftToolBar: self.zValue.setText("0.00") self.textValue = self._lineedit("textValue", self.layout) + # shapestring + + self.labelSSize = self._label("labelSize", self.layout) + self.SSizeValue = self._lineedit("SSizeValue", self.layout, width=60) + self.SSizeValue.setText("200.0") + self.labelSTrack = self._label("labelTracking", self.layout) + self.STrackValue = self._lineedit("STrackValue", self.layout, width=60) + self.STrackValue.setText("0") + self.labelSString = self._label("labelString", self.layout) + self.SStringValue = self._lineedit("SStringValue", self.layout) + self.SStringValue.setText("") + self.labelFFile = self._label("labelFFile", self.layout) + self.FFileValue = self._lineedit("FFileValue", self.layout) + defFile = Draft.getParam("FontFile") + if defFile: + self.FFileValue.setText(defFile) + else: + self.FFileValue.setText("") + self.chooserButton = self._pushbutton("chooserButton", self.layout, width=26) + self.chooserButton.setText("...") + # options - + self.numFaces = self._spinbox("numFaces", self.layout, 3) self.offsetLabel = self._label("offsetlabel", self.layout) self.offsetValue = self._lineedit("offsetValue", self.layout, width=60) @@ -386,7 +407,20 @@ class DraftToolBar: QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("escaped()"),self.escape) QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("resized()"),self.relocate) QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("retranslate()"),self.retranslateUi) + QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric) + QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("escaped()"),self.escape) + QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric) + QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("escaped()"),self.escape) + QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("returnPressed()"),self.validateSString) + QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("escaped()"),self.escape) + QtCore.QObject.connect(self.chooserButton,QtCore.SIGNAL("pressed()"),self.pickFile) + QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("returnPressed()"),self.validateFile) + QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("escaped()"),self.escape) +# if Ui changed to have Size & Track visible at same time, use this +# QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.checkSSize) +# QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.checkSTrack) + def setupTray(self): "sets draft tray buttons up" @@ -478,6 +512,15 @@ class DraftToolBar: self.resetPlaneButton.setToolTip(translate("draft", "Do not project points to a drawing plane")) self.isCopy.setText(translate("draft", "&Copy")) self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved (C)")) + self.SStringValue.setToolTip(translate("draft", "Text string to draw")) + self.labelSString.setText(translate("draft", "String")) + self.SSizeValue.setToolTip(translate("draft", "Height of text")) + self.labelSSize.setText(translate("draft", "Height")) + self.STrackValue.setToolTip(translate("draft", "Intercharacter spacing")) + self.labelSTrack.setText(translate("draft", "Tracking")) + self.labelFFile.setText(translate("draft", "Pick a font file")) + self.chooserButton.setToolTip(translate("draft", "Open a FileChooser for font file")) + if (not self.taskmode) or self.tray: self.wplabel.setToolTip(translate("draft", "Set/unset a working plane")) self.colorButton.setToolTip(translate("draft", "Line Color")) @@ -528,6 +571,15 @@ class DraftToolBar: self.offsetLabel.show() self.offsetValue.show() + def hideXYZ(self): + ''' turn off all the point entry widgets ''' + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + def lineUi(self,title=None): if title: self.pointUi(title,icon="Draft_Line") @@ -606,12 +658,7 @@ class DraftToolBar: else: self.setTitle(translate("draft", "None")) self.labelx.setText(translate("draft", "X")) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() + self.hideXYZ() self.numFaces.hide() self.isRelative.hide() self.hasFill.hide() @@ -634,6 +681,15 @@ class DraftToolBar: self.textValue.hide() self.continueCmd.hide() self.occOffset.hide() + self.labelSString.hide() + self.SStringValue.hide() + self.labelSSize.hide() + self.SSizeValue.hide() + self.labelSTrack.hide() + self.STrackValue.hide() + self.labelFFile.hide() + self.FFileValue.hide() + self.chooserButton.hide() def trimUi(self,title=translate("draft","Trim")): self.taskUi(title) @@ -643,29 +699,56 @@ class DraftToolBar: self.radiusValue.selectAll() def radiusUi(self): - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() + self.hideXYZ() self.labelRadius.setText(translate("draft", "Radius")) self.labelRadius.show() self.radiusValue.show() def textUi(self): - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() + self.hideXYZ() self.textValue.show() self.textValue.setText('') self.textValue.setFocus() self.textbuffer=[] self.textline=0 self.continueCmd.show() + + def SSUi(self): + ''' set up ui for ShapeString text entry ''' + self.hideXYZ() + self.labelSString.show() + self.SStringValue.show() + self.SStringValue.setText('') + self.SStringValue.setFocus() + self.continueCmd.hide() + + def SSizeUi(self): + ''' set up ui for ShapeString size entry ''' + self.labelSString.hide() + self.SStringValue.hide() + self.continueCmd.hide() + self.labelSSize.show() + self.SSizeValue.setText('200.0') + self.SSizeValue.show() + self.SSizeValue.setFocus() + + def STrackUi(self): + ''' set up ui for ShapeString tracking entry ''' + self.labelSSize.hide() + self.SSizeValue.hide() + self.labelSTrack.show() + self.STrackValue.setText('0') + self.STrackValue.show() + self.STrackValue.setFocus() + + def SFileUi(self): + ''' set up UI for ShapeString font file selection ''' + self.labelSTrack.hide() + self.STrackValue.hide() + self.labelFFile.show() + self.FFileValue.show() + self.chooserButton.show() + self.FFileValue.setFocus() def switchUi(self,store=True): if store: @@ -676,12 +759,7 @@ class DraftToolBar: self.state.append(self.xValue.isVisible()) self.state.append(self.yValue.isVisible()) self.state.append(self.zValue.isVisible()) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() + self.hideXYZ() else: if self.state: if self.state[0]:self.labelx.show() @@ -707,12 +785,7 @@ class DraftToolBar: def editUi(self): self.taskUi(translate("draft", "Edit")) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() + self.hideXYZ() self.numFaces.hide() self.isRelative.hide() self.hasFill.hide() @@ -902,6 +975,74 @@ class DraftToolBar: numz = last.z + v.z self.sourceCmd.numericInput(numx,numy,numz) + def validateSNumeric(self): + ''' send valid numeric parameters to ShapeString ''' + if self.sourceCmd: + if (self.labelSSize.isVisible()): + try: + SSize=float(self.SSizeValue.text()) + except ValueError: + FreeCAD.Console.PrintMessage(translate("draft", "Invalid Size value. Using 200.0.")) + self.sourceCmd.numericSSize(unicode("200.0")) + else: + self.sourceCmd.numericSSize(unicode(SSize)) + elif (self.labelSTrack.isVisible()): + try: + track=int(self.STrackValue.text()) + except ValueError: + FreeCAD.Console.PrintMessage(translate("draft", "Invalid Tracking value. Using 0.")) + self.sourceCmd.numericSTrack(unicode("0")) + else: + self.sourceCmd.numericSTrack(unicode(track)) + + def validateSString(self): + ''' send a valid text string to ShapeString as unicode ''' + if self.sourceCmd: + if (self.labelSString.isVisible()): + if self.SStringValue.text(): +# print "debug: D_G DraftToolBar.validateSString type(SStringValue.text): " str(type(self.SStringValue.text)) + self.sourceCmd.validSString(str(self.SStringValue.text().toUtf8())) # QString to QByteArray to PyString + else: + FreeCAD.Console.PrintMessage(translate("draft", "Please enter a text string.")) + + + def pickFile(self): + ''' invoke a font file chooser dialog and send result to ShapeString to''' + if self.sourceCmd: + if (self.chooserButton.isVisible()): + try: + dialogCaption = translate("draft", "Select a Font file") + dialogDir = os.path.dirname(Draft.getParam("FontFile")) + if not dialogDir: + dialogDir = os.getcwd() # reasonable default? + dialogFilter = "Fonts (*.ttf *.pfb *.otf);;All files (*.*)" + fname = QtGui.QFileDialog.getOpenFileName(self.baseWidget, + dialogCaption, + dialogDir, + dialogFilter) + fname = str(fname.toUtf8()) # QString to PyString +# print "debug: D_G DraftToolBar.pickFile type(fname): " str(type(fname)) + + except Exception as e: + FreeCAD.Console.PrintMessage("DraftGui.pickFile: unable to select a font file.") + print type(e) + print e.args + else: + if fname: + self.sourceCmd.validFFile(fname) + else: + FreeCAD.Console.PrintMessage("DraftGui.pickFile: no file selected.") # can this happen? + + def validateFile(self): + ''' check and send font file parameter to ShapeString as unicode''' + if self.sourceCmd: + if (self.labelFFile.isVisible()): + if self.FFileValue.text(): + self.sourceCmd.validFFile(str(self.FFileValue.text().toUtf8())) #QString to PyString + else: + FreeCAD.Console.PrintMessage(translate("draft", "Please enter a font file.")) + + def finish(self): "finish button action" if self.sourceCmd: @@ -1222,7 +1363,8 @@ class DraftToolBar: self.commands = ["Draft_Line","Draft_Wire", "Draft_Rectangle","Draft_Arc", "Draft_Circle","Draft_BSpline", - "Draft_Text","Draft_Dimension"] + "Draft_Text","Draft_Dimension", + "Draft_ShapeString"] self.title = "Create objects" def shouldShow(self): return (FreeCAD.ActiveDocument != None) and (not FreeCADGui.Selection.getSelection()) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index fbff806a57..da6d5e53d1 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1786,6 +1786,118 @@ class Dimension(Creator): self.createObject() if not self.cont: self.finish() +class ShapeString(Creator): + "This class creates a shapestring feature." + + def GetResources(self): + return {'Pixmap' : 'Draft_ShapeString', + 'Accel' : "S, S", + 'MenuShapeString': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "ShapeString"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "Creates text string in shapes.")} + + def Activated(self): + name = str(translate("draft","ShapeString")) + Creator.Activated(self,name) + if self.ui: + self.ui.sourceCmd = self + self.dialog = None + self.text = '' + self.ui.sourceCmd = self + self.ui.pointUi(name) + self.call = self.view.addEventCallback("SoEvent",self.action) + self.ui.xValue.setFocus() + self.ui.xValue.selectAll() + msg(translate("draft", "Pick ShapeString location point:\n")) + FreeCADGui.draftToolBar.show() + + def createObject(self): + "creates object in the current doc" +# print "debug: D_T ShapeString.createObject type(self.SString): " str(type(self.SString)) + # temporary code + import platform + if not (platform.system() == 'Linux'): +# if (platform.system() == 'Linux'): + FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet fully implemented for your platform.\n") + self.finish() + return + # temporary code + + dquote = '"' + String = dquote + self.SString + dquote + Size = str(self.SSSize) # numbers are ascii so this should always work + Tracking = str(self.SSTrack) # numbers are ascii so this should always work + FFile = dquote + self.FFile + dquote +# print "debug: D_T ShapeString.createObject type(String): " str(type(String)) +# print "debug: D_T ShapeString.createObject type(FFile): " str(type(FFile)) + + try: + qr,sup,points,fil = self.getStrings() + self.commit(translate("draft","Create ShapeString"), + ['import Draft', + 'ss=Draft.makeShapeString(String='+String+',FontFile='+FFile+',Size='+Size+',Tracking='+Tracking+')', + 'plm=FreeCAD.Placement()', + 'plm.Base='+DraftVecUtils.toString(self.point), + 'plm.Rotation.Q='+qr, + 'ss.Placement=plm', + 'ss.Support='+sup]) + except Exception as e: + msg("Draft_ShapeString: error delaying commit", "error") + print type(e) + print e.args + self.finish() + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + self.point,ctrlPoint,info = getPoint(self,arg) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if self.point: + self.node.append(self.point) + self.ui.SSUi() + + def numericInput(self,numx,numy,numz): + '''this function gets called by the toolbar when valid + x, y, and z have been entered there''' + self.point = Vector(numx,numy,numz) + self.node.append(self.point) + self.ui.SSUi() #move on to next step in parameter entry + + def numericSSize(self,ssize): + '''this function is called by the toolbar when valid size parameter + has been entered. ''' + self.SSSize = ssize + self.ui.STrackUi() + + def numericSTrack(self,strack): + '''this function is called by the toolbar when valid size parameter + has been entered. ?''' + self.SSTrack = strack + self.ui.SFileUi() + + def validSString(self,sstring): + '''this function is called by the toolbar when a ?valid? string parameter + has been entered. ''' + self.SString = sstring + self.ui.SSizeUi() + + def validFFile(self,FFile): + '''this function is called by the toolbar when a ?valid? font file parameter + has been entered. ''' + self.FFile = FFile + # last step in ShapeString parm capture, create object + self.createObject() + + def finish(self, finishbool=False): + "terminates the operation" + Creator.finish(self) + if self.ui: +# del self.dialog # what does this do?? + if self.ui.continueMode: + self.Activated() #--------------------------------------------------------------------------- # Modifier functions @@ -3584,6 +3696,7 @@ FreeCADGui.addCommand('Draft_Polygon',Polygon()) FreeCADGui.addCommand('Draft_BSpline',BSpline()) FreeCADGui.addCommand('Draft_Point',Point()) FreeCADGui.addCommand('Draft_Ellipse',Ellipse()) +FreeCADGui.addCommand('Draft_ShapeString',ShapeString()) # modification commands FreeCADGui.addCommand('Draft_Move',Move()) diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 995e6ab1b5..b521dbd33e 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,8 +2,8 @@ # Resource object code # -# Created: Thu Apr 11 13:50:17 2013 -# by: The Resource Compiler for PyQt (Qt v4.8.2) +# Created: Mon Apr 15 12:19:38 2013 +# by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -41412,61 +41412,61 @@ qt_resource_data = "\ \x29\xcc\x8c\x7b\xd7\x67\x66\xb2\xc1\x7c\x9a\x4a\x32\x65\x74\x40\ \x19\x6d\xf1\x44\x1c\xdb\x22\x23\xbc\x6e\xd6\x13\xde\xda\xfb\x3f\ \x76\xfc\xff\x17\ -\x00\x00\x10\x85\ +\x00\x00\x10\xc0\ \x00\ -\x00\xa9\x59\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ -\x0f\xbd\x1e\xd0\x8d\x63\xe7\xdd\x3a\x3e\xb4\xe9\x13\x68\x77\xd3\ -\x3a\x6d\x6f\xef\xcb\x82\x96\x68\x9b\x57\x59\xf2\x92\x74\x12\x2f\ -\xee\xc7\xdf\x0c\x49\x59\x8f\xc8\x72\x64\x59\x96\xbd\x75\x51\x20\ +\x00\xae\x67\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ +\x0f\xbd\x1e\xd0\x8d\x63\xe7\xdd\x75\x7c\x68\xd3\x27\xd0\xee\xa6\ +\x75\xda\xde\xde\x97\x05\x2d\xd1\x36\xaf\xb2\xe4\x25\xe9\x24\x5e\ +\xdc\x8f\xbf\x19\x92\xb2\x1e\x91\xe5\xc8\xb2\x2c\xbb\x75\x51\x20\ \x16\x49\x91\xc3\xe1\xbc\x38\x33\xa4\xda\xff\xba\x1f\x79\xe4\x96\ \x09\xc9\x03\xff\x72\xbf\x79\x70\xb8\x4f\x98\xef\x04\x2e\xf7\x07\ -\x97\xfb\x5f\x6f\xde\xfe\x72\xbe\xff\xaf\xce\x5e\x7b\xc2\xa3\x46\ -\xc7\xd0\xa8\xb3\x47\xda\x8e\x47\xa5\xec\xbc\x9b\xf0\xe7\xcf\x5f\ -\x73\xea\x05\x03\xf8\xeb\x0d\xba\x4c\x29\x78\x59\xbe\x16\xb4\xaf\ -\xda\x0d\xd3\x08\x5a\xdf\x71\x77\xc0\x14\xd1\xcf\x97\xfb\x9f\xbf\ -\xeb\xc7\x7d\xe2\xd3\x11\xbb\xdc\xcf\xed\x04\x07\x23\xed\xb1\x08\ +\x97\xfb\x5f\x6e\xde\xfc\x72\xbe\xff\xaf\xce\x5e\x7b\xc2\xa3\x46\ +\xc7\xd0\xa8\xb3\x47\xda\x8e\x47\xa5\xec\xbc\x9d\xf0\xe7\xcf\x5f\ +\x71\xea\x05\x03\xf8\xeb\x0d\xba\x4c\x29\x78\x59\xbe\x12\xb4\xaf\ +\xda\x0d\xd3\x08\x5a\xdf\x71\x77\xc0\x14\xd1\xcf\x97\xfb\x9f\xbe\ +\xe9\xc7\x7d\xe2\xd3\x11\xbb\xdc\xcf\xed\x04\x07\x23\xed\xb1\x08\ \xc6\x4c\xa8\xa9\x7d\x63\xc0\x82\x11\x53\x62\xaa\x2b\x49\x5b\x30\ \x47\xe9\x5f\xa4\x7d\xdf\x39\x6c\x37\xee\xed\xc3\x14\x1f\xa6\xf6\ -\x01\x40\x50\xc3\xce\xc9\x05\x14\x99\x9f\xa6\x78\xc8\xf8\x60\xa8\ -\x3a\xa7\x47\xad\x76\xc3\xfe\xd6\x7d\x36\xc2\x4e\xdb\x8d\x70\xf0\ +\x01\x40\x50\xc3\xce\x59\xf3\xbc\xdd\x30\x3f\x4d\xf1\x90\xf1\xc1\ +\x50\x75\xce\x0f\xa1\xdc\xfe\xd6\x7d\x36\xc2\x4e\xdb\x8d\x70\xf0\ \x2c\x48\xee\xb8\xef\x06\x77\x37\x5c\x79\xcc\x02\x23\x95\x00\xe0\ -\x3b\xef\x98\xcf\x04\xf5\x88\xb4\x93\x69\x37\x6c\xc5\xc3\x2e\x3d\ -\x3a\x0d\x26\x11\x72\xbe\xbd\x0a\xee\x3f\xea\x22\xdb\x63\x6a\x48\ +\x3b\x6f\x99\xcf\x04\xf5\x88\xb4\x93\x69\x37\x6c\xc5\xc3\x2e\x3d\ +\x3a\x0d\x26\x11\x72\xbe\xbe\x0c\xee\x3f\xe8\x22\xdb\x63\x6a\x48\ \x39\xa6\x0e\x74\xb4\x6f\x27\xe0\x4f\x46\x3d\x26\x3a\xa7\xed\x86\ \xfd\x65\xc0\x8f\x8f\xf0\xa0\x8b\x11\x15\x03\xee\xa7\x7a\xb8\xc8\ -\xed\x81\x2b\x36\x8a\x30\x19\x5f\xcc\x77\x22\x98\x8c\x01\xe6\x70\ +\xed\x81\x2b\x36\x8a\x30\x19\x5f\xcc\xb7\x22\x98\x8c\x01\xe6\x70\ \x39\x07\xe1\xb3\x69\xfe\x60\x70\x15\x21\x2b\x03\x5f\x7a\xd1\x49\ \x37\x03\x6b\x0f\x81\xca\xc5\x9d\x1d\x0d\x08\x57\x71\x87\x7a\xa6\ -\xf4\x8f\x56\x34\x70\x34\xa3\x8c\x8e\xde\x3f\xe8\x68\x18\x08\xfe\ -\x57\xe0\xab\x59\x57\xcd\x8b\x59\x5f\xe9\xde\x1e\x20\x49\x93\xf8\ -\xb5\x60\xfd\xab\x21\x73\x7e\xc4\x91\x85\x15\x63\xa8\x70\xb0\xa2\ -\x17\xdc\xff\xd1\x6c\xc5\xba\xcd\xc0\x5e\x10\x78\x37\x7c\x9c\x68\ -\x33\x43\xe2\x87\x3e\x51\x43\x2e\x09\xfc\xd7\xfd\x31\xf7\x19\x14\ -\x30\x8b\xd4\xbb\x40\xfc\xe8\x01\x7f\x0f\xe1\x97\xff\x0f\x45\xe8\ -\x78\xcc\xa8\x38\x20\x5f\x25\xeb\x4f\x80\x52\xb9\xef\x30\x42\x3d\ +\xf4\xcf\x56\x34\x70\x34\xa3\x8c\x8e\xde\x3d\xe8\x68\x18\x08\xfe\ +\x77\xe0\xab\x59\x57\xcd\x8b\x59\x5f\xe9\xde\x1e\x20\x49\x93\xf8\ +\xb5\x60\xfd\xab\x21\x73\xbe\xc7\x91\x85\x15\x63\xa8\x70\xb0\xa2\ +\x17\xdc\xff\xd9\x6c\xc5\xba\xcd\xc0\x5e\x10\x78\x37\x7c\x9c\x68\ +\x33\x43\xe2\xfb\x3e\x51\x43\x2e\x09\xfc\xd7\xfd\x31\xf7\x19\x14\ +\x30\x8b\xd4\xbb\x40\x7c\xef\x01\x7f\x0f\xe1\x97\xff\x0f\x45\xe8\ +\x78\xcc\xa8\x38\x20\x5f\x24\xeb\x4f\x80\x52\xb9\xef\x30\x42\x3d\ \x8f\x04\xfd\xd8\x5b\x38\xa0\x24\x54\x60\x95\x0c\x08\xf7\x75\xdd\ -\x4b\xa1\xbb\xb1\x1d\x1e\xa4\xd6\x29\x7b\xb1\xb2\xe7\xc3\xee\x55\ -\xf6\x64\xde\x73\xf7\x01\xe4\xcb\x8f\x83\x38\x7e\xe3\xa3\xcc\x20\ +\x0b\xa1\xbb\xb1\x1d\x1e\xa4\xd6\x29\x7b\xb1\xb2\xe7\xc3\xee\x55\ +\xf6\x64\xde\x71\xf7\x01\xe4\xcb\x8f\x83\x38\x7e\xed\xa3\xcc\x20\ \x52\xb9\xc0\x95\x97\xfb\x87\xa9\x71\x1d\xdb\xf7\x10\x06\xd6\xe3\ -\x7e\x8f\x86\x75\xca\x8c\x7b\x4d\xd5\x70\xf1\xb0\x9f\x02\xb7\x11\ +\x7e\x8b\x86\x75\xca\x8c\x7b\x4d\xd5\x70\xf1\xb0\x1f\x03\xb7\x11\ \xca\xcd\x47\x8e\xa6\x45\x19\x90\x59\x8c\x0e\x1b\x49\x42\x5c\x40\ -\x97\x9f\x3f\xd2\x1e\xf3\x42\x62\xf4\xf0\x21\x49\xd7\x45\x16\xcc\ +\x97\x9f\x3e\xd0\x1e\xf3\x42\x62\xf4\xf0\x21\x49\xd7\x45\x16\xcc\ \xac\x15\xf7\x15\x13\x7d\x0a\xa4\x34\x0a\x5c\xb6\xfc\x82\x51\x8f\ -\x0f\xfc\x11\xf3\x1f\x0c\x06\xd3\xfd\xac\x9e\x3f\x7f\x89\xf5\x5f\ -\x50\x60\xff\x6f\xf6\x78\x23\x28\xf7\x60\xb4\xa8\xe4\xdb\x15\x43\ +\x0f\xfc\x11\xf3\x1f\x0c\x06\xd3\xfd\xa4\x9e\x3f\x7f\x81\xf5\x9f\ +\x51\x60\xff\x6f\xf6\x78\x23\x28\xf7\x60\xb4\xa8\xe4\xeb\x15\x43\ \x78\x00\x8c\x38\x96\xaa\x42\x67\xc4\xe6\xc1\xa8\x17\x64\xb2\x39\ -\x56\x20\x9b\x1f\x2f\xcf\xe5\x37\x96\xc5\x91\x0f\xbf\x7e\xd0\x68\ +\x56\x20\x9b\x1f\x2f\xcf\xe5\x37\x96\xc5\x91\x0f\xbf\xbc\xd7\x68\ \x46\xb6\xbc\x1b\x72\xe0\xc9\x88\x71\xa1\x7c\xe2\x31\x72\xc7\x81\ \xa3\x91\x81\x9e\x93\x1b\xe8\xb5\x47\x85\x79\x43\x97\x8f\x3d\x6a\ \x79\xde\xbc\x13\x6a\x2b\xec\x8f\xc2\xd3\x98\x0a\xaa\x98\x96\x01\ -\xf0\xe2\x33\x1c\x03\xba\x54\x54\xfe\x48\xf6\x33\x91\x4c\x8f\xfc\ -\x56\x30\x76\xf5\xf2\x35\xb9\x81\x16\xb7\x9c\xdd\x11\x39\x95\x80\ +\xf0\xe2\x33\x1c\x03\xba\x54\x54\x7e\x4f\xf6\x33\x91\x4c\x8f\xfc\ +\x46\x30\x76\xf5\xe2\x15\xb9\x81\x16\xb7\x9c\xdd\x11\x39\x95\x80\ \x31\xd2\x0f\x84\x1e\x85\x2b\x89\x6d\x85\xa1\x12\xea\x28\xb0\x29\ -\xd6\xc2\xd3\x5f\xf9\x27\x4d\x8d\x9b\xc9\xc7\x0f\xe8\xea\x31\x6c\ +\xd6\xc2\xd3\x5f\xf8\x47\x4d\x8d\x9b\xc9\xc7\x0f\xe8\xea\x31\x6c\ \x17\xd1\x83\x59\x9d\x2c\x3c\xce\x1b\xae\x91\x1e\xaf\x1c\x00\x76\ \xb5\xcb\x40\xb0\x90\xf7\xda\x0d\xa3\xa2\x67\xfa\x3b\x51\x5d\x5a\ \x9b\xb7\x1e\xaf\xcc\xb3\x84\xe6\x02\xa5\x3d\x5f\x66\xb2\x3e\x9d\ -\x78\xd0\x75\xe0\x05\x99\x2b\x58\xb9\xa0\x82\x71\x5f\x4d\x94\x0a\ +\x78\xd0\x75\xe0\x05\x99\x2b\x58\xb9\xa0\x82\x71\x5f\x4e\x94\x0a\ \xfc\x0c\x59\x05\x75\x3d\x53\xb7\xb4\xb0\x42\xa9\xe0\xc6\x27\xa9\ \x65\x81\x0f\xa2\x21\xe8\xfd\x17\x4c\xec\xb4\x89\x97\x47\x33\xa9\ \x71\x75\x77\x69\x26\xc4\xb2\x14\x95\x0a\xe6\xe2\x46\x00\xff\x24\ @@ -41484,201 +41484,204 @@ qt_resource_data = "\ \x5b\x67\x66\x2b\xe1\xd6\x2c\xd4\x6b\x01\x92\x8f\x2d\xda\x96\x92\ \x7a\xc5\xfb\xab\xa3\x92\xfb\xab\xc3\x52\xaa\x8d\x72\x2d\xb4\x6b\ \xd1\x6a\x8b\x3c\x41\x27\x65\xf4\x19\x23\xb3\x09\xa2\xd2\x82\x39\ -\xf2\x3e\x67\x82\xfc\x60\xd3\xb5\xf8\x55\x60\x40\x27\x04\x60\x53\ +\xf2\x3e\x67\x82\x7c\x67\xd3\xb5\xf8\x55\x60\x40\x27\x04\x60\x53\ \x49\xbf\x9c\x73\x43\x0e\x39\x0e\x56\x97\x6f\xc5\x51\xc2\xab\x6f\ \x74\xea\x95\x9a\xfa\x12\x6c\x84\xd1\x2d\xa0\xdf\xb4\x14\xe9\xea\ \xe2\x05\xbc\x02\xad\x19\x34\x46\xb3\x23\x45\x3d\x0c\x54\x80\xf6\ -\x1a\xbf\x9f\xf5\xd8\x6e\xe8\xc2\xc2\xa4\x2a\xf9\x5f\xec\x3d\xf7\ -\xd5\x7c\x52\xc5\x16\x29\x74\x9a\x88\xe3\x71\x32\xf6\x38\xab\xb5\ -\x71\xc7\xd6\x61\x22\x04\x19\x81\x95\xee\x70\x8e\xc8\x32\xa8\x5b\ -\xa9\x2d\xd3\x6a\x96\xd9\x96\x6f\xaa\xc4\x3d\x2d\x27\x71\xa5\x9d\ -\xdb\x0a\x24\xad\x33\x11\x02\x48\xf6\x83\xef\xb2\xfb\x6c\xf3\xa5\ -\xb9\x16\xf3\x05\x66\x83\xb3\xda\x49\x70\x53\xba\x93\xe0\x51\xc1\ -\x8a\x25\x78\x3e\xef\xed\x24\xf8\xca\x25\xf8\xb2\x91\x89\x97\x9e\ -\xda\x58\x01\x7e\x56\x4e\x80\x53\x33\xb5\xb5\xc8\xef\xf5\x6c\x3f\ -\x61\x36\x9a\xd1\x77\xe2\x7b\x27\xbe\x37\x29\xaa\xda\x8c\x53\xd1\ -\x32\xb9\x28\xe5\xb6\xfd\xd6\x5d\xab\x33\xd2\xf4\x2b\x35\x48\xb3\ -\x8f\xdc\x67\x6f\x5c\xae\x1e\x48\x33\x74\x19\x31\xa8\x28\x13\x1d\ -\xca\x72\x68\x47\xb3\xd5\xfe\xb5\x84\xe3\x3a\x4c\x9c\xac\x22\x5f\ -\x2b\x8e\xf2\xb5\xf8\x1e\xe2\x33\xd3\x93\x36\x2b\xbc\x99\x32\xb0\ -\x6e\x4e\x3c\x7e\x3c\x23\x3e\x3e\x59\x71\x79\xc2\xd5\x3d\xd8\x64\ -\xc5\x3e\x01\x08\xc9\x1d\xf5\x31\xd9\x70\x96\x4a\xa4\x03\x07\x8d\ -\x98\xaf\x58\x04\x23\x5d\x61\x93\x91\x08\x95\x21\xc9\x57\x41\xcd\ -\x5d\x7a\x0b\x30\x18\xf5\x6e\x63\x44\xd4\x77\x63\xbe\x6b\xea\x88\ -\x40\x4a\x22\x99\xc4\xc4\xe8\x12\xbe\xeb\x22\x51\x4d\x00\x2a\xf0\ -\xd9\x3d\xdf\x58\x55\x5f\x37\x99\x9f\x55\x41\xe6\x65\x5c\xb4\x59\ -\x29\xb9\x4e\x30\x9e\xc6\x92\xe7\x7a\x0c\x8c\xd0\xb1\x0a\x29\x0a\ -\xac\xdc\x11\x90\xda\x33\x12\x00\xb5\x8b\x3b\x2e\x59\x58\x24\x4d\ -\x7b\xea\xdd\xd1\x29\x50\x9e\xa2\x02\xd3\x2d\x89\x1f\xfc\x32\xeb\ -\xb1\x0a\x56\x78\xe7\x05\x3d\xea\x91\x15\x8c\x61\x31\x90\x1a\xa6\ -\x07\xf8\xeb\x80\x20\x87\x8e\xf5\xcf\x6a\x75\xc6\x78\x3a\xda\xe0\ -\x4c\xc0\xba\xf9\xa7\x79\x5e\x09\x03\x95\x88\xd9\xff\x1a\x88\x11\ -\xf5\xbc\xe9\x33\x02\x88\x64\x42\x93\x21\x86\x3a\x6c\xcc\xf0\x99\ -\x55\x16\x63\xce\x24\x41\xe0\x24\xf3\xa0\x9c\xb9\x07\x24\x64\xbd\ -\x60\xac\x6d\x9f\x74\x52\x7c\x8f\x02\x67\x85\x31\xff\x90\x11\xc3\ -\xb7\x81\xaf\xa4\x62\xd4\xad\x24\xb3\xbd\xab\x07\x49\x02\x90\x98\ -\xdc\x7a\x94\x89\x86\xe2\x15\x00\xf1\x5b\x18\x7e\xdd\xf1\x44\x16\ -\x4f\x9c\x54\xc2\x12\xe7\xab\xd5\x29\xda\x84\x8a\x6b\x07\x74\x52\ -\x83\x39\x05\xc6\x82\x54\x31\x7e\xb1\x19\x2d\x98\xdd\x02\xa5\x9a\ -\x49\xfc\x40\xc5\xde\xef\x19\x07\xf7\x58\xbf\xe3\x7b\x53\x78\x81\ -\xf9\x04\x40\x07\x3b\x07\x8a\xae\x6e\xbe\x7c\xac\x84\x29\x5e\x26\ -\xe1\x0e\xc1\x7d\xea\x72\x49\x7b\x5e\xe4\x75\x47\x87\xcd\x3f\xb7\ -\x59\x05\x99\x05\xea\x6e\xb0\xbb\x7d\xe5\x4e\xdf\xfc\x1d\xee\xce\ -\xe9\xbb\x6a\xa7\x6f\xb3\xa4\x83\x54\x50\x97\x4f\xe4\x2c\xd3\x54\ -\xcb\x02\xe0\x49\x39\x66\x0e\x07\x4b\x70\x1c\x00\x22\xe5\x01\x9e\ -\xd2\xc3\xe2\x43\x93\xc7\x13\x10\x60\x55\x45\xf1\x10\xd9\x53\xee\ -\xf7\xb9\x0f\x70\x97\x60\xd4\x05\xb1\x45\x41\xfd\x41\x1d\xee\x9c\ -\x05\x19\x52\x0b\x48\x5d\x4e\xfa\x7d\x9e\xf6\x14\xdb\x39\x8c\xef\ -\xd7\xa3\xf6\x01\x7b\x5f\x0c\xf2\xb6\x54\xfa\x54\x7d\x12\xa4\x80\ -\xcf\xb2\x80\xbe\x2f\x71\xe0\x2b\x4b\xdf\xcf\xf8\x52\x2b\x6d\x50\ -\xe1\x24\x70\x9c\x89\x20\x74\x40\xd1\x74\x8d\x19\xb6\x6a\x08\x6a\ -\x53\xa0\x53\x85\x9a\xb3\x9b\xdc\x77\xb9\x43\xd1\xc8\x35\x91\x09\ -\x3c\xef\xc9\x60\x56\x25\x7c\x18\x8b\x12\x01\xe8\x3d\x1f\x4d\x46\ -\x95\x68\xed\x3e\xf5\xe4\x3a\xd4\x36\xcc\xe1\x67\xd2\xd9\x3b\x8d\ -\x3d\x1f\xd3\x55\x84\x69\xf3\x77\xc8\xcc\x47\x1b\x78\xf5\xf4\x9f\ -\x2b\x76\x3e\x19\xae\x4d\x4b\x09\x54\xf9\x3d\xa6\xe3\x0a\xdc\x65\ -\x02\xc4\x48\xdc\x4e\xa8\x42\x86\xcc\x01\x64\x03\xb5\x7f\x7e\x76\ -\x43\x55\xab\x68\xc5\x6b\x76\x00\xfa\xe2\xe2\x62\xf9\x10\x74\x5e\ -\x5e\xf5\xf1\x7a\x22\xdb\x46\xec\xbe\x31\x0b\xbe\xa5\xb2\xb7\x6a\ -\x8b\xa5\x59\x89\xc5\x52\x62\x13\x01\x16\x4b\xc2\xd7\xd6\x35\xbb\ -\x7a\x13\xb8\x99\xb9\x19\x86\x81\x3e\x61\xc3\x7c\x76\x0b\x6c\x8d\ -\x1e\x08\x0c\xfe\x54\x29\x49\xba\x30\x64\x78\xc5\x48\x0c\xa4\x6d\ -\x76\x27\x20\x16\x71\x2e\xaf\xe8\xdf\xf7\x98\x4d\x01\xa2\x5d\xf6\ -\x08\x5c\xec\xb6\x11\x19\x27\x56\xe3\x97\x9d\xc8\x12\x51\x8f\x82\ -\x57\x8f\x6c\xfb\x62\x56\x1d\xa1\x28\x70\x52\xbf\xc8\xb5\x3b\x0b\ -\x32\x9d\xf3\xa4\x1d\x8f\x49\x3b\x4a\x2c\x08\x76\x97\xa5\x5d\x27\ -\xc3\x28\x94\x8c\x37\x71\x60\xd9\xd8\xa3\x3e\x23\x31\x43\xda\x5e\ -\xc7\x23\x89\x3b\xc1\x4e\x43\x0f\x2d\x41\x30\x74\x83\x6a\xb6\x67\ -\x28\x10\xbf\x5b\x98\xae\x35\x4c\x4a\x50\x98\x4a\x09\x99\x58\x50\ -\x78\xe9\x51\x6f\xc2\x41\x77\x44\x9f\x45\xf4\xd5\x44\xe5\x4a\xe4\ -\xc1\x67\xb9\x24\x12\xb1\x34\x43\xcd\x98\xa4\xd1\x87\x47\xd8\x24\ -\x44\xe9\x1a\x07\xe4\xb7\x30\xb2\xad\xad\x83\x69\xfa\x8d\x3b\x0e\ -\x50\x8a\x22\xe9\x5a\x05\x28\xfe\x2d\x8e\x35\x3b\xea\x3b\x2d\x9f\ -\x43\x52\x80\xdc\x11\x15\xbb\xe8\xf3\x7c\x32\x2f\x70\xa3\x5a\xa6\ -\xdb\xbb\xec\x2d\x2c\x09\xe1\xbc\x91\x99\xcf\xf9\x33\x2c\x40\x8a\ -\x96\xec\xbf\x5f\x6f\x2a\x2d\x96\xcb\x9b\xfd\x35\xc8\x5e\xc0\xf5\ -\x64\xed\xfe\xfb\x77\xf2\xf4\x26\x18\x67\x46\x3f\xd6\x04\xc1\x7f\ -\xc8\xd3\xb7\x02\x78\xab\x46\x18\x7e\x07\x18\xba\x60\xd0\x96\x02\ -\xa1\x6e\x91\xd4\xac\x26\xa3\xac\xdc\x25\x8f\x31\x6b\x73\x20\xb8\ -\x9b\xd0\x9f\x3a\x5c\x6f\x8d\xc7\x2a\xf4\xe7\x57\xd8\xa2\xe3\xa0\ -\x5b\xed\xcc\x37\x13\xd8\x4c\xc1\xb7\xf2\xe8\x7b\xbe\x1f\x67\xe7\ -\xcb\x2f\xe3\xcb\x2f\xb2\xc3\xcc\x3f\xcb\x50\x8b\x8b\x3f\xed\xa7\ -\x33\x0e\x90\x98\x4c\x31\x49\x39\x3d\x46\x6e\xb9\xe4\x98\x86\xa3\ -\xc5\x4b\xd6\x9d\xb2\xb0\x13\xc0\xfb\x1c\x6f\x59\xcc\xbc\x8f\x25\ -\x10\x4d\x74\xf6\x10\x0d\x53\x59\xab\xcc\x20\x82\x3d\xe5\x5a\xac\ -\x79\x9b\xc8\x03\xc3\xbd\xfb\x7b\x89\x93\x47\x58\xda\xf9\x19\xd1\ -\x95\xd1\xf2\xfc\x1c\x65\x24\x59\x7b\x33\x76\x0d\x86\xfb\xeb\x60\ -\x02\x13\x9e\x17\x1d\x72\x75\x6d\x18\x23\xda\xc0\x48\x9f\x3e\xd5\ -\x6e\x90\x07\xbc\xae\xee\x18\x30\x2c\xa3\xc0\xd4\x5a\x12\xe0\x99\ -\x87\xe5\x19\xca\x65\x0e\x1f\x01\xe4\xd9\x51\xa4\x12\x41\xa4\xec\ -\xa8\x97\xc1\x35\x46\xbd\x2e\x0e\x2e\xce\x2f\x66\xff\xce\xce\x5b\ -\xed\x86\xad\x2c\x3c\x54\x56\x18\xcc\xf6\xd5\x3c\x38\x4c\xfe\x5b\ -\x7e\x94\x82\xf6\x4b\x37\xa4\xf6\x9f\x49\xee\xd4\x13\x60\xcd\x0b\ -\x4d\x73\x5f\x33\x88\x24\x18\xc4\x7a\xfc\xc1\xba\xf5\xc5\xa4\xf3\ -\x13\x8f\x6a\xca\x2c\xe0\xbe\x41\x5a\x18\x0b\x34\xb7\xed\xa9\x21\ -\x47\x2f\xf0\x01\xe9\x62\xa6\x61\x7f\x4a\xc0\x8e\x60\x04\x5d\xd4\ -\x60\x33\x4c\x89\xfc\x73\x42\x05\x93\x33\x11\x35\x0a\xbb\x29\x91\ -\x90\x9c\x13\xe1\x6e\x1e\xae\x25\xc2\x8d\xbc\xfc\xc6\xd0\xce\x96\ -\x72\x72\xd5\x5b\xf0\x92\x77\x87\x2d\xc8\xb4\x9f\xcb\xdb\x1f\xf0\ -\x8e\x72\x1f\xf3\x5d\x05\x50\x23\x9e\xf2\x23\x1e\x30\x79\xe6\x69\ -\xf0\x9a\x79\x3c\xdf\xa6\xb0\x9a\xb2\x0b\x3b\xa2\xc7\xee\xba\x4e\ -\xf3\x77\x5d\xcd\xd3\xb3\xb3\xb3\x56\xf3\xa4\xcc\xde\xab\xb8\x89\ -\x12\xe5\xff\x84\x46\x05\x1e\x7f\xe3\xe1\x32\x39\x41\x20\x5c\xee\ -\x53\xc5\x64\x2c\x6a\x46\x9e\x62\x7a\x12\xbb\x3f\x20\x47\xe4\x92\ -\x1c\x82\xba\x6e\x96\xc8\x4a\xce\x11\x17\xa7\x6b\x91\x16\x33\x5a\ -\xdc\x5a\x69\x51\xd4\x7d\x91\xaf\xbf\x76\xee\x8b\x95\x1f\x1e\x58\ -\x56\x5e\xbe\xe6\x23\xe6\xeb\xc3\xd0\x5b\x20\x31\xf3\x37\xb0\xb9\ -\x19\x75\xe7\xd5\xe4\xd3\xad\x45\x7c\xb8\x7c\x74\xbd\xf5\x12\xa4\ -\x6a\x7b\xa3\xc0\x81\xbf\x2c\x06\x5a\x90\x37\x37\x97\x7f\x6e\x02\ -\x0f\x94\x96\xef\x54\x1a\x79\xcc\x97\xb5\xf9\xac\xbf\x93\xb5\x2b\ -\x71\x15\x17\x70\x16\xfd\x04\x66\x5d\x74\x81\x8d\x16\x8e\x98\x6a\ -\xe7\x62\x5e\x46\x7f\xe2\x3b\xc6\x80\x53\x43\xaa\x74\x66\x28\x25\ -\x2a\x64\x91\x83\xbd\x6f\xd8\xda\x9e\x6f\x71\x79\xbf\x0f\x3b\x45\ -\x28\xc7\xcd\xa1\x07\xfb\x45\x9d\x9c\x62\x3a\x0c\xb7\x98\x4a\x30\ -\x7d\xe8\x85\x4a\x22\x01\xb0\x12\x7b\xc6\x9c\x53\x5c\x8d\x65\x08\ -\xde\x1f\x00\x39\x28\x96\x46\x91\xf5\x23\x81\xc9\xda\x5c\x91\x87\ -\x29\xc7\x8f\x05\xa3\x9c\xac\xdf\x8f\xa5\x22\x91\xb7\xd3\x45\x59\ -\xba\xe8\xb4\x9c\x2a\x5a\x90\xe1\xb5\x30\x21\x06\x5b\x10\x23\x0b\ -\x36\xdc\xab\x9e\x1f\x50\xff\x3b\x88\xca\x70\x4d\xcc\x78\xfa\xd0\ -\x0d\x2e\x8f\xd4\xf7\x12\xb9\x33\xdb\x7b\xb5\x7b\xdb\x99\x74\x68\ -\xd5\xe0\xe5\xc6\xe9\x85\xc4\xb7\xa5\xe2\xa1\xa8\x01\x96\xef\xc8\ -\xd9\x19\x60\xab\xde\xec\x2e\xb8\xd9\xe9\x71\x02\xb2\x0f\xf8\xde\ -\xc4\x9b\x05\x97\xcf\x31\xca\xba\x57\x10\x67\xa9\xdf\x9d\x7d\xcd\ -\xd1\x7e\x20\x36\x43\x08\x1d\xec\x7d\x00\x78\xa9\x8f\x76\x17\x8d\ -\xbd\x29\x27\xce\x10\x0d\xb0\x27\x7f\x4e\x02\xf5\xe2\xa5\xe0\xd4\ -\x33\x3f\x31\x95\x29\x1c\x48\xaa\xa9\x97\x6e\x2a\xa9\x2f\xc3\x96\ -\xb6\x84\x09\xde\x37\x3f\xf7\x00\x1e\xf3\x6b\x14\xf8\x41\xd8\x0c\ -\x81\x24\x7d\x3a\xe2\xde\x34\x6b\xdc\x67\xef\x99\x77\xcb\xf0\xdb\ -\xc0\xcf\xa2\xce\xcd\x4b\x1a\x54\x6d\x58\x52\x03\xcc\x5e\xc6\xfb\ -\xcf\x5f\x05\x9e\x6b\x9e\x2b\x49\x66\xc0\x31\xb6\xea\xeb\xa9\x65\ -\x25\xbd\xe1\xa2\x2d\x95\xf3\x55\xbb\x24\x0a\x9c\xf0\xcb\xf4\xe9\ -\x2d\x7b\x8f\x7f\x24\xe7\x46\x63\x0f\x3f\x05\x2b\x87\x8c\x55\x2a\ -\xec\xf2\xf5\xe3\x82\x89\xec\x14\xe4\x4a\x3c\x14\x6f\xb9\xc7\xae\ -\x86\x41\x00\x32\xf6\x81\x72\xe9\x43\x9d\x63\xea\x16\x19\xdd\xdc\ -\x2f\x6a\x74\x1f\x1d\xe6\x23\xa8\x14\x7e\x8a\x07\x9c\xdc\x34\xf5\ -\xdb\xfb\x49\x75\x46\x9b\x83\xfe\x04\x93\xd4\x86\xdf\xb0\x0a\xcf\ -\x6b\x15\x63\x90\x72\x42\xd3\x40\xb5\x13\x9a\xd9\x42\xb3\x55\xd1\ -\x49\xc1\x12\x97\x19\x7e\x37\xd9\x93\xa9\x83\x53\x51\x3a\x25\xbe\ -\x6c\x93\x22\x34\x79\x31\x72\x8d\x97\x7c\x8e\x05\x1f\x71\xcc\xad\ -\x94\xe1\xbd\x84\x18\x04\x35\xaf\xcc\xee\x41\xd4\x44\x49\x6f\x41\ -\x87\x63\x46\x47\x25\x77\xb4\x61\xee\xb7\x06\xe8\x7a\x06\xd0\x7a\ -\xbe\xde\x2d\x19\x0e\x1b\x1f\x75\x47\xf2\x99\x76\x42\x81\x6b\x9e\ -\x33\xec\x84\xf2\x81\xbf\x27\x74\x34\x7e\x41\x3e\x02\x85\x82\x0e\ -\xa7\x42\x04\x77\xc6\x82\xde\xc4\xc3\x54\x2b\x3b\x4a\xc5\x47\xe6\ -\x53\xbc\x9b\x4a\x95\xe5\x8e\xf1\xbc\x0e\x14\x39\xa9\xef\x14\x11\ -\x0e\x7f\x56\xef\xf0\x17\xf5\x0d\x7f\xc5\x85\x03\x9b\xe1\x1a\xf1\ -\x6f\x21\xa8\x71\x09\x2c\x04\x35\xae\x42\x17\x44\xcb\xb0\xce\x45\ -\x30\x00\xd4\xb8\x06\x06\x80\x1a\x97\xe0\x15\x75\x7e\xc8\xba\x97\ -\x21\x02\xa2\xc6\xa5\x88\x80\x28\xb5\x1c\xb5\x9b\x2a\x25\x43\x5b\ -\xcd\xfc\xbc\xb0\xf9\xd6\xca\x37\x68\xc5\x1d\xea\xc5\xdc\x95\xc6\ -\x8d\x1b\x73\x1e\x6c\xa2\xb9\xb2\xaa\x0f\x9f\xc7\xef\x1c\x09\xfa\ -\xc6\xc5\x1b\x62\xc2\x3a\x73\xed\x21\x2f\xd8\xe3\xc7\x91\x44\x05\ -\x23\xb7\x16\x79\x07\x24\xf4\x0c\x41\xaf\x1e\xeb\x2b\xdc\x7f\x70\ -\x73\x0c\x0c\x7b\xfc\xd0\xfd\x0d\x3f\x50\xe0\xbb\x54\x94\xb9\x43\ -\xbd\x98\x15\x96\x58\xc0\xbf\xa3\x29\xf6\x11\x10\x4d\x9e\xc6\x71\ -\x5b\xe3\xf1\xee\x2f\xf3\xa2\xc2\x5b\x22\x81\x4a\x8a\x9f\x65\x3f\ -\xf3\xfe\xd2\xd3\xe9\xca\xb0\xb5\xef\x7e\x7b\x07\xbb\x69\x85\x8f\ -\xc0\x43\x81\x53\xb9\xe4\x59\xe0\x5a\xcd\x3f\x9f\xba\x73\xad\xae\ -\xd5\xb5\xba\x20\xa3\x7f\xab\x5d\xab\xef\xf1\x54\x0f\x5e\xf7\x87\ -\x11\x42\x69\x8f\xfa\x50\x50\x35\x82\x39\x2a\x10\x53\xbc\x5b\x54\ -\xd9\x2f\x9a\x23\x93\x20\x5e\x64\xbc\xf0\x89\xa7\x5e\x8c\x0d\xe7\ -\x3c\x19\xa8\x17\xe8\xa7\xc5\xeb\xc6\xa3\x6c\xb1\x30\xf4\xe8\xba\ -\xcc\x45\xa7\x2d\xaa\xa4\x50\x64\x5a\xbf\x19\x34\x03\x75\x65\x7b\ -\x59\x8f\x1b\xcb\x0e\x86\x24\xb0\xa9\xfa\xa9\x9c\x4c\x4e\x56\x26\ -\xfa\x8a\xda\xc5\x1a\xc5\x5a\x58\xf9\x3d\x8b\x01\x9b\xc3\x8d\x97\ -\xfb\xa7\xfb\x64\x44\xc5\x80\xfb\x97\xfb\xcd\xe6\x3e\xa6\xd7\xb5\ -\xc7\xfc\x7e\x44\xc7\x61\x7e\x60\xe7\xcf\x6b\xfd\xfc\x56\x04\xa3\ -\x4f\x60\xac\x74\x83\x89\xc0\x7c\xb2\x54\x2b\x78\xcf\x99\x48\x15\ -\x8c\xcc\x88\x52\x43\x12\x2f\x31\x50\x6a\x76\xed\x68\x6e\x8d\x71\ -\x2a\xe0\x4f\x97\xeb\x26\x20\xd9\x99\xef\xca\xce\xe7\xef\xfa\x3d\ -\x10\x75\xb6\x60\xcf\x70\x13\xba\xbe\xb0\x87\x06\x76\xf0\x9a\x53\ -\x2f\x18\x1c\x0c\x91\xb9\x74\x85\x46\x40\x7a\xdc\x7c\x40\xae\xf0\ -\xeb\x63\xaf\x26\x4a\x69\xb3\x26\x03\x90\xeb\x89\x1c\x86\xf5\xf3\ -\x80\x31\xc0\xca\x72\x90\xa4\x04\x58\x26\x34\x0f\x71\x37\x0f\x24\ -\xec\x6d\x65\x60\xd9\x2c\xb1\x6c\x04\xcd\x2a\xd7\x02\xca\xa2\xf5\ -\x7a\xb8\xa8\xeb\x01\xcb\x46\x36\xb2\x51\x14\xd5\xae\x09\x47\x66\ -\xb7\x33\x07\x98\x59\xed\x5a\x80\x09\x13\x69\xb2\x81\x89\x6a\xd7\ -\x02\x4c\x22\xe9\x31\x1b\xa2\x54\x93\xf2\x60\x25\x0b\xb0\xa7\xb6\ -\x60\x52\x0b\x52\xa9\x45\x2e\xe8\x5e\x9f\x99\x74\x6c\x33\x8b\xd9\ -\xb3\x19\x55\x02\x00\xd0\x77\xc6\x3d\x47\x98\x3b\xe2\xdb\x71\xd1\ -\x3a\x19\xf8\xd4\xeb\x38\x1e\x9e\xf3\x75\x9f\xe2\xd1\x62\xdc\xc1\ -\x98\x52\xdd\x02\x4c\x00\xc6\x6f\xe3\x7d\xa5\x6e\x4f\x68\x37\x66\ -\x4d\x4c\x97\x5e\xa0\x3a\xa0\x06\xdf\x98\x83\xcc\xb3\x3e\xb1\xd8\ -\x60\x04\x3f\x56\x62\x35\x12\xfe\x26\x6a\x3a\x46\x53\x53\x4f\x2f\ -\x11\xf6\x68\xdf\x77\x2e\x00\xe0\xfb\xf0\x71\xda\x39\x3a\xbb\x68\ -\x37\xa6\xa1\x3a\xc3\xb7\x1f\x76\xe4\x32\xfc\xc0\x92\x36\x8c\xd3\ -\xbd\x1d\x37\xcf\x92\xdd\x9d\x37\xb3\xba\x33\x3f\xa5\x5d\x9a\x04\ -\x6a\xd7\x8a\xe9\xd9\x89\xf1\x6a\x71\x8c\x38\x4d\xe0\xf8\xa8\x0c\ -\x8e\x4f\xce\x9a\xa9\xee\x8e\x2b\xc3\xf1\xf1\xea\x70\x7c\x5a\x2d\ -\x8e\x4f\x93\x84\xd7\x3a\x3b\x5c\x25\x8e\x5b\x67\xad\x0d\xc4\x71\ -\xf8\x25\x85\x8a\x31\xdb\x5a\x29\x66\x9b\xa7\x6b\xc3\xec\xf2\x12\ -\x22\xbc\xf4\xa7\x5a\xcc\x9e\x9c\x27\x19\xf9\xf4\xa4\x0c\x66\x8f\ -\x4e\x8e\xb7\x40\xf6\x86\xd7\x9a\x54\x8b\xd9\xa3\xa3\x14\x66\xcf\ -\x56\x49\xb3\x55\x62\xf6\xac\xbc\xc4\x8d\xae\x86\xaf\x16\xc9\xcd\ -\x14\xfd\xb6\x2e\x4a\x49\x86\x63\xf4\xd7\x24\xba\xcb\x54\x93\x9b\ -\x62\x3b\xc4\xae\xb9\xab\xd8\x7a\x48\x5b\x68\xa5\xa4\x44\xab\x75\ -\xfa\x18\x63\x64\x3e\x96\xe3\x8f\x50\xdf\x6e\x4c\x78\x67\xef\xff\ -\x40\xba\x52\xd7\ +\x1a\xbf\x9b\xf5\xd8\x6e\xe8\xc2\xc2\xa4\x2a\xf9\xdf\xec\x1d\xf7\ +\xd5\x7c\x52\xc5\x16\x29\x74\x9a\x88\xe3\xf1\x61\x22\xf6\x38\xab\ +\xb5\x71\xc7\xd6\x61\x22\x04\x19\x81\x95\xee\x70\x8e\xc8\x32\xa8\ +\x5b\xa9\x2d\xd3\x6a\x96\xd9\x96\x6f\xaa\xc4\x3d\x2d\x27\x71\xa5\ +\x9d\xdb\x0a\x24\xad\x33\x11\x02\x48\xf6\xbd\xef\xb2\xfb\x6c\xf3\ +\xa5\xb9\x16\xf3\x05\x66\x83\xb3\xda\x49\x70\x53\xba\x93\xe0\x51\ +\xc1\x8a\x25\x78\x3e\xef\xed\x24\xf8\xca\x25\xf8\xb2\x91\x89\x17\ +\x9e\xda\x58\x01\x7e\x56\x4e\x80\x53\x33\xb5\xb5\xc8\xef\xf5\x6c\ +\x3f\x61\x36\x9a\xd1\x77\xe2\x7b\x27\xbe\x37\x29\xaa\xda\x8c\x53\ +\xd1\x32\xb9\x28\xe5\xb6\xfd\xd6\x5d\xab\x33\xd2\xf4\x2b\x35\x48\ +\xb3\x0f\xdc\x67\xaf\x5d\xae\x1e\x48\x33\x74\x19\x31\xa8\x28\x13\ +\x1d\xca\x72\x68\x47\xb3\xd5\xfe\xb5\x84\xe3\x3a\x4c\x9c\xac\x22\ +\x5f\x2b\x8e\xf2\xb5\xf8\x1e\xe2\x33\xd3\x93\x36\x2b\xbc\x99\x32\ +\xb0\x6e\x4e\x3c\x7e\x3c\x23\x3e\x3e\x59\x71\x79\xc2\xd5\x3d\xd8\ +\x64\xc5\x3e\x01\x08\xc9\x1d\xf5\x31\xd9\x70\x96\x4a\xa4\x03\x07\ +\x8d\x98\xaf\x58\x04\x23\x5d\x61\x93\x91\x08\x95\x21\xc9\x57\x41\ +\xcd\x5d\x7a\x0b\x30\x18\xf5\x6e\x63\x44\xd4\x77\x63\xbe\x6b\xea\ +\x88\x40\x4a\x22\x99\xc4\xc4\xe8\x12\xbe\xeb\x22\x51\x4d\x00\x2a\ +\xf0\xd9\x3d\xdf\x58\x55\x5f\x37\x99\x9f\x55\x41\xe6\x65\x5c\xb4\ +\x59\x29\xb9\x4e\x30\x9e\xc6\x92\xe7\x7a\x0c\x8c\xd0\xb1\x0a\x29\ +\x0a\xac\xdc\x11\x90\xda\x33\x12\x00\xb5\x8b\x3b\x2e\x59\x58\x24\ +\x4d\x7b\xea\xdd\xd1\x29\x50\x9e\xa2\x02\xd3\x2d\x89\x1f\xfc\x32\ +\xeb\xb1\x0a\x56\x78\xeb\x05\x3d\xea\x91\x15\x8c\x61\x31\x90\x1a\ +\xa6\x07\xf8\xeb\x80\x20\x87\x8e\xf5\xcf\x6a\x75\xc6\x78\x3a\xda\ +\xe0\x4c\xc0\xba\xf9\xa7\x79\x5e\x09\x03\x95\x88\xd9\xff\x16\x88\ +\x11\xf5\xbc\xe9\x33\x02\x88\x64\x42\x93\x21\x86\x3a\x6c\xcc\xf0\ +\x99\x55\x16\x63\xce\x24\x41\xe0\x24\xf3\xa0\x9c\xb9\x07\x24\x64\ +\xbd\x60\xac\x6d\x9f\x74\x52\x7c\x8f\x02\x67\x85\x31\xff\x90\x11\ +\xc3\xb7\x81\xaf\xa4\x62\xd4\xad\x24\xb3\xbd\xab\x07\x49\x02\x90\ +\x98\xdc\x7a\x94\x89\x86\xe2\x25\x00\xf1\x7b\x18\x7e\xdd\xf1\x44\ +\x16\x4f\x9c\x54\xc2\x12\xe7\xab\xd5\x29\xda\x84\x8a\x6b\x07\x74\ +\x52\x83\x39\x05\xc6\x82\x54\x31\x7e\xb1\x19\x2d\x98\xdd\x02\xa5\ +\x9a\x49\xfc\x40\xc5\xde\xef\x19\x07\xf7\x58\xbf\xe3\x7b\x53\x78\ +\x81\xf9\x04\x40\x07\x3b\x07\x8a\xae\x6e\x3e\x7f\xa8\x84\x29\x5e\ +\x24\xe1\x0e\xc1\x7d\xea\x72\x49\x7b\x5e\xe4\x75\x47\x87\xcd\x3f\ +\xb7\x59\x05\x99\x05\xea\x6e\xb0\xbb\x7d\xe5\x4e\xdf\xfc\x1d\xee\ +\xce\xe9\xbb\x6a\xa7\x6f\xb3\xa4\x83\x54\x50\x97\x4f\xe4\x2c\xd3\ +\x54\xcb\x02\xe0\x49\x39\x66\x0e\x07\x4b\x70\x1c\x00\x22\xe5\x01\ +\x9e\xd2\xc3\xe2\x43\x93\xc7\x13\x10\x60\x55\x45\xf1\x10\xd9\x53\ +\xee\xf7\xb9\x0f\x70\x97\x60\xd4\x05\xb1\x45\x41\xfd\x41\x1d\xee\ +\x9c\x05\x19\x52\x0b\x48\x5d\x4e\xfa\x7d\x9e\xf6\x14\xdb\x39\x8c\ +\xef\xd7\xa3\xf6\x01\x7b\x9f\x0d\xf2\xb6\x54\xfa\x54\x7d\x12\xa4\ +\x80\xcf\xb2\x80\xbe\x2f\x71\xe0\x2b\x4b\xdf\xcf\xf8\x52\x2b\x6d\ +\x50\xe1\x24\x70\x9c\x89\x20\x74\x40\xd1\x74\x8d\x19\xb6\x6a\x08\ +\x6a\x53\xa0\x53\x85\x9a\xb3\x9b\xdc\x77\xb9\x43\xd1\xc8\x35\x91\ +\x09\x3c\xef\xc9\x60\x56\x25\x7c\x18\x8b\x12\x01\xe8\x3d\x1f\x4d\ +\x46\x95\x68\xed\x3e\xf5\xe4\x3a\xd4\x36\xcc\xe1\x67\xd2\xd9\x3b\ +\x8d\x3d\x1f\xd3\x55\x84\x69\xf3\x77\xc8\xcc\x47\x1b\x78\xf5\xf4\ +\x9f\x2b\x76\x3e\x1a\xae\x4d\x4b\x09\x54\xf9\x3d\xa6\xe3\x0a\xdc\ +\x65\x02\xc4\x48\xdc\x4e\xa8\x42\x86\xcc\x01\x64\x03\xb5\x7f\x7e\ +\x76\x43\x55\xab\x68\xc5\x6b\x76\x00\xfa\xe2\xe2\x62\xf9\x10\x74\ +\x5e\x5e\xf5\xf1\x7a\x22\xdb\x46\xec\xbe\x36\x0b\xbe\xa5\xb2\xb7\ +\x6a\x8b\xa5\x59\x89\xc5\x52\x62\x13\x01\x16\x4b\xc2\xd7\xd6\x35\ +\xbb\x7a\x13\xb8\x99\xb9\x19\x86\x81\x3e\x61\xc3\x7c\x76\x0b\x6c\ +\x8d\x1e\x08\x0c\xfe\x54\x29\x49\xba\x30\x64\x78\xc5\x48\x0c\xa4\ +\x6d\x76\x27\x20\x16\x71\x2e\x2f\xe9\x8f\x7b\xcc\xa6\x00\xd1\x2e\ +\x7b\x04\x2e\x76\xdb\x88\x8c\x13\xab\xf1\xcb\x4e\x64\x89\xa8\x47\ +\xc1\xab\x47\xb6\x7d\x31\xab\x8e\x50\x14\x38\xa9\x5f\xe4\xda\x9d\ +\x05\x99\xce\x79\xd2\x8e\xc7\xa4\x1d\x25\x16\x04\xbb\xcb\xd2\xae\ +\x93\x61\x14\x4a\xc6\x9b\x38\xb0\x6c\xec\x51\x9f\x91\x98\x21\x6d\ +\xaf\xe3\x91\xc4\x9d\x60\xa7\xa1\x87\x96\x20\x18\xba\x41\x35\xdb\ +\x33\x14\x88\xdf\x2c\x4c\xd7\x1a\x26\x25\x28\x4c\xa5\x84\x4c\x2c\ +\x28\xbc\xf4\xa8\x37\xe1\xa0\x3b\xa2\xcf\x22\xfa\x6a\xa2\x72\x25\ +\xf2\xe0\xb3\x5c\x12\x89\x58\x9a\xa1\x66\x4c\xd2\xe8\xc3\x23\x6c\ +\x12\xa2\x74\x8d\x03\xf2\x7b\x18\xd9\xd6\xd6\xc1\x34\xfd\xc6\x1d\ +\x07\x28\x45\x91\x74\xad\x02\x14\xff\x06\xc7\x9a\x1d\xf5\x9d\x96\ +\xcf\x21\x29\x40\xee\x88\x8a\x5d\xf4\x79\x3e\x99\x17\xb8\x51\x2d\ +\xd3\xed\x5d\xf6\x16\x96\x84\x70\xde\xc8\xcc\xe7\xfc\x19\x16\x20\ +\x45\x4b\xf6\xdf\xae\x37\x95\x16\xcb\xe5\xcd\xfe\x16\x64\x2f\xe0\ +\x7a\xb2\x76\xff\xfd\x07\x79\x7a\x13\x8c\x33\xa3\x1f\x6b\x82\xe0\ +\x3f\xe4\xe9\x1b\x01\xbc\x55\x23\x0c\x7f\x00\x0c\x5d\x30\x68\x4b\ +\x81\x50\xb7\x48\x6a\x56\x93\x51\x56\xee\x92\xc7\x98\xb5\x39\x10\ +\xdc\x4d\xe8\x4f\x1d\xae\xb7\xc6\x63\x15\xfa\xf3\x0b\x6c\xd1\x71\ +\xd0\xad\x76\xe6\x9b\x09\x6c\xa6\xe0\x5b\x79\xf4\x3d\xdf\x8f\xb3\ +\xf3\xe5\x97\xf1\xe5\x17\xd9\x61\xe6\x9f\x65\xa8\xc5\xc5\x9f\xf6\ +\xd3\x19\x07\x48\x4c\xa6\x98\xa4\x9c\x1e\x23\xb7\x5c\x72\x4c\xc3\ +\xd1\xe2\x25\xeb\x4e\x59\xd8\x09\xe0\x7d\x8e\xb7\x2c\x66\xde\xc7\ +\x12\x88\x26\x3a\x7b\x88\x86\xa9\xac\x55\x66\x10\xc1\x9e\x72\x2d\ +\xd6\xbc\x4d\xe4\x81\xe1\xde\xfe\x58\xe2\xe4\x11\x96\x76\x7e\x46\ +\x74\x65\xb4\x3c\x3f\x47\x19\x49\xd6\xde\x8c\x5d\x83\xe1\xfe\x2a\ +\x98\xc0\x84\xe7\x45\x87\x5c\x5d\x1b\xc6\x88\x36\x30\xd2\xa7\x4f\ +\xb5\x1b\xe4\x01\xaf\xab\x3b\x06\x0c\xcb\x28\x30\xb5\x96\x04\x78\ +\xe6\x61\x79\x86\x72\x99\xc3\x47\x00\x79\x76\x14\xa9\x44\x10\x29\ +\x3b\xea\x65\x70\x8d\x51\xaf\x8b\x83\x8b\xf3\x8b\xd9\xbf\xb3\xf3\ +\x56\xbb\x61\x2b\x0b\x0f\x95\x15\x06\xb3\x7d\x35\x0f\x0e\x93\xff\ +\x96\x1f\xa5\xa0\xfd\xd2\x0d\xa9\xfd\x67\x92\x3b\xf5\x04\x58\xf3\ +\x42\xd3\xdc\xd7\x0c\x22\x09\x06\xb1\x1e\x7f\xb0\x6e\x7d\x31\xe9\ +\xfc\xc4\xa3\x9a\x32\x0b\xb8\x6f\x90\x16\xc6\x02\xcd\x6d\x7b\x6a\ +\xc8\xd1\x0b\x7c\x40\xba\x98\x69\xd8\x9f\x12\xb0\x23\x18\x41\x17\ +\x35\xd8\x0c\x53\x22\xff\x9a\x50\xc1\xe4\x4c\x44\x8d\xc2\x6e\x4a\ +\x24\x24\xe7\x44\xb8\x9b\x87\x6b\x89\x70\x23\x2f\xbf\x36\xb4\xb3\ +\xa5\x9c\x5c\xf5\x16\xbc\xe4\xdd\x61\x0b\x32\xed\xe7\xf2\xf6\x7b\ +\xbc\xa3\xdc\xc7\x7c\x57\x01\xd4\x88\xa7\xfc\x88\x07\x4c\x9e\x79\ +\x1a\xbc\x66\x1e\xcf\xb7\x29\xac\xa6\xec\xc2\x8e\xe8\xb1\xbb\xae\ +\xd3\xfc\x5d\x57\xf3\xf4\xec\xec\xac\xd5\x3c\x29\xb3\xf7\x2a\x6e\ +\xa2\x44\xf9\x3f\xa1\x51\x81\xc7\xdf\x78\xb8\x4c\x4e\x10\x08\x97\ +\xfb\x54\x31\x19\x8b\x9a\x91\xa7\x98\x9e\xc4\xee\x0f\xc8\x11\xb9\ +\x24\x87\xa0\xae\x9b\x25\xb2\x92\x73\xc4\xc5\xe9\x5a\xa4\xc5\x8c\ +\x16\xb7\x56\x5a\x14\x75\x5f\xe4\xeb\xaf\x9d\xfb\x62\xe5\x87\x07\ +\x96\x95\x97\xaf\xf8\x88\xf9\xfa\x30\xf4\x16\x48\xcc\xfc\x0d\x6c\ +\x6e\x46\xdd\x79\x35\xf9\x74\x6b\x11\x1f\x2e\x1f\x5d\x6f\xbd\x04\ +\xa9\xda\xde\x28\x70\xe0\x2f\x8b\x81\x16\xe4\xcd\xcd\xe5\x9f\x9b\ +\xc0\x03\xa5\xe5\x3b\x95\x46\x1e\xf3\x65\x6d\x3e\xeb\xef\x64\xed\ +\x4a\x5c\xc5\x05\x9c\x45\x3f\x81\x59\x17\x5d\x60\xa3\x85\x23\xa6\ +\xda\xb9\x98\x97\xd1\x9f\xf8\x8e\x31\xe0\xd4\x90\x2a\x9d\x19\x4a\ +\x89\x0a\x59\xe4\x60\xef\x2b\xb6\xb6\xe7\x5b\x5c\xde\xef\xc3\x4e\ +\x11\xca\x71\x73\xe8\xc1\x7e\x51\x27\xa7\x98\x0e\xc3\x2d\xa6\x12\ +\x4c\x1f\x7a\xa1\x92\x48\x00\xac\xc4\x9e\x31\xe7\x14\x57\x63\x19\ +\x82\xf7\x07\x40\x0e\x8a\xa5\x51\x64\xfd\x48\x60\xb2\x36\x57\xe4\ +\x61\xca\xf1\x63\xc1\x28\x27\xeb\xf7\x63\xa9\x48\xe4\xed\x74\x51\ +\x96\x2e\x3a\x2d\xa7\x8a\x16\x64\x78\x2d\x4c\x88\xc1\x16\xc4\xc8\ +\x82\x0d\xf7\xaa\xe7\x07\xd4\x7f\x04\x51\x19\xae\x89\x19\x4f\x1f\ +\xba\xc1\xe5\x91\xfa\x5e\x22\x77\x66\x7b\xaf\x76\x6f\x3b\x93\x0e\ +\xad\x1a\xbc\xdc\x38\xbd\x90\xf8\xb6\x54\x3c\x14\x35\xc0\xf2\x1d\ +\x39\x3b\x03\x6c\xd5\x9b\xdd\x05\x37\x3b\x3d\x4e\x40\xf6\x01\xdf\ +\x9b\x78\xb3\xe0\xf2\x39\x46\x59\xf7\x0a\xe2\x2c\xf5\xbb\xb3\xaf\ +\x39\xda\x0f\xc4\x66\x08\xa1\x83\xbd\xf7\x00\x2f\xf5\xd1\xee\xa2\ +\xb1\x37\xe5\xc4\x19\xa2\x01\xf6\xe4\xaf\x49\xa0\x7e\x7d\x21\x38\ +\xf5\xcc\x4f\x4c\x65\x0a\x07\x92\x6a\xea\xa5\x9b\x4a\xea\xcb\xb0\ +\xa5\x2d\x61\x82\xf7\xcd\xcf\x3d\x80\xc7\xfc\x1a\x05\x7e\x10\x36\ +\x43\x20\x49\x9f\x8e\xb8\x37\xcd\x1a\xf7\xd9\x3b\xe6\xdd\x32\xfc\ +\x36\xf0\xb3\xa8\x73\xf3\x92\x06\x55\x1b\x96\xd4\x00\xb3\x97\xf1\ +\xfe\xf3\x97\x81\xe7\x9a\xe7\x4a\x92\x19\x70\x8c\xad\xfa\x7a\x6a\ +\x59\x49\x6f\xb8\x68\x4b\xe5\x7c\xd5\x2e\x89\x02\x27\xfc\x32\x7d\ +\x7a\xcb\xde\xe3\x1f\xc9\xb9\xd1\xd8\xc3\x4f\xc1\xca\x21\x63\x95\ +\x0a\xbb\x7c\xfd\xb8\x60\x22\x3b\x05\xb9\x12\x0f\xc5\x1b\xee\xb1\ +\xab\x61\x10\x80\x8c\x7d\xa0\x5c\xfa\x50\xe7\x98\xba\x45\x46\x37\ +\xf7\x8b\x1a\xdd\x47\x87\xf9\x08\x2a\x85\x9f\xe2\x01\x27\x37\x4d\ +\xfd\xf6\x7e\x52\x9d\xd1\xe6\xa0\x3f\xc1\x24\xb5\xe1\x37\xac\xc2\ +\xf3\x5a\xc5\x18\xa4\x9c\xd0\x34\x50\xed\x84\x66\xb6\xd0\x6c\x55\ +\x74\x52\xb0\xc4\x65\x86\xdf\x4c\xf6\x64\xea\xe0\x54\x94\x4e\x89\ +\x2f\xdb\xa4\x08\x4d\x5e\x8c\x5c\xe3\x25\x9f\x63\xc1\x47\x1c\x73\ +\x2b\x65\x78\x2f\x21\x06\x41\xcd\x2b\xb3\x7b\x10\x35\x51\xd2\x5b\ +\xd0\xe1\x98\xd1\x51\xc9\x1d\x6d\x98\xfb\xad\x01\xba\x9e\x01\xb4\ +\x9e\xaf\x77\x4b\x86\xc3\xc6\x47\xdd\x91\x7c\xa6\x9d\x50\xe0\x9a\ +\xe7\x0c\x3b\xa1\x7c\xe0\xef\x09\x1d\x8d\x7f\x25\x1f\x80\x42\x41\ +\x87\x53\x21\x82\x3b\x63\x41\x6f\xe2\x61\xaa\x95\x1d\xa5\xe2\x23\ +\xf3\x29\xde\x4d\xa5\xca\x72\xc7\x78\x5e\x05\x8a\x9c\xd4\x77\x8a\ +\x08\x87\x3f\xab\x77\xf8\x8b\xfa\x86\xbf\xe2\xc2\x81\xcd\x70\x8d\ +\xf8\xb7\x10\xd4\xb8\x04\x16\x82\x1a\x57\xa1\x0b\xa2\x65\x58\xe7\ +\x22\x18\x00\x6a\x5c\x03\x03\x40\x8d\x4b\xf0\x92\x3a\xdf\x65\xdd\ +\xcb\x10\x01\x51\xe3\x52\x44\x40\x94\x5a\x8e\xda\x4d\x95\x92\xa1\ +\xad\x66\x7e\x5e\xd8\x7c\x6b\xe5\x2b\xb4\xe2\x0e\xf5\x62\xee\x4a\ +\xe3\xc6\x8d\x39\x0f\x36\xd1\x5c\x59\xd5\x87\xcf\xe3\x77\x8e\x04\ +\x7d\xe3\xe2\x0d\x31\x61\x9d\xb9\xf6\x90\x17\xec\xf1\xe3\x48\xa2\ +\x82\x91\x5b\x8b\xbc\x03\x12\x7a\x86\xa0\x57\x8f\xf5\x15\xee\x3f\ +\xb8\x39\x06\x86\x3d\xbe\xef\xfe\x8e\x1f\x28\xf0\x5d\x2a\xca\xdc\ +\xa1\x5e\xcc\x0a\x4b\x2c\xe0\x8f\x68\x8a\x7d\x00\x44\x93\xa7\x71\ +\xdc\xd6\x78\xbc\xfb\xf3\xbc\xa8\xf0\x96\x48\xa0\x92\xe2\x67\xd9\ +\xcf\xbc\xbf\xf0\x74\xba\x32\x6c\xed\xbb\x5f\xdf\xc2\x6e\x5a\xe1\ +\x23\xf0\x50\xe0\x54\x2e\x79\x16\xb8\x56\xf3\xcf\xa7\xee\x5c\xab\ +\x6b\x75\xad\x2e\xc8\xe8\xdf\x6a\xd7\xea\x3b\x3c\xd5\x83\xd7\xfd\ +\x61\x84\x50\xda\xa3\x3e\x14\x54\x8d\x60\x8e\x0a\xc4\x14\xef\x16\ +\x55\xf6\x8b\xe6\xc8\x24\x88\x17\x19\x2f\x7c\xe2\xa9\x5f\xc7\x86\ +\x73\x9e\x0c\xd4\xaf\xe8\xa7\xc5\xeb\xc6\xa3\x6c\xb1\x30\xf4\xe8\ +\xba\xcc\x45\xa7\x2d\xaa\xa4\x50\x64\x5a\xbf\x19\x34\x03\x75\x65\ +\x7b\x59\x8f\x1b\xcb\x0e\x86\x24\xb0\xa9\xfa\xa9\x6e\xab\xb0\x55\ +\xf2\xac\x4f\x6b\x59\xab\x30\x34\x67\xba\x43\x3a\x66\x5d\x5d\x46\ +\xde\x60\xdc\xda\xac\x56\x5d\x42\x39\xff\x3a\xc3\x9d\x4c\x5e\xa7\ +\x4c\xfe\x81\x25\xb2\xfd\x22\x91\x4d\xd5\xe8\x17\x21\xf9\x32\x02\ +\x11\x19\xec\xc7\x95\x86\xc9\xca\x44\x5f\x51\xbb\x58\xa3\x58\x0b\ +\x2b\x39\x67\x19\x31\xe6\xa8\xf7\xe5\xfe\xe9\x3e\x19\x51\x31\xe0\ +\xfe\xe5\x7e\xb3\xb9\x8f\xc9\xc6\xed\x31\xbf\x1f\xd1\x71\x98\x2d\ +\xdd\xf9\xeb\x5a\x3f\xbf\x11\xc1\xe8\x23\x6c\xdd\xba\xc1\x44\x60\ +\x76\x6d\xaa\x15\xbc\xe7\x4c\xa4\x0a\x46\x66\x44\xa9\x21\x89\x97\ +\x18\x28\x35\xa3\x74\x34\x9f\xc4\x78\x04\xf0\xa7\xcb\x75\x13\x10\ +\xa8\xcc\x77\x65\xe7\xd3\x37\xfd\x1e\x08\x19\x5b\xb0\x67\x28\x19\ +\x03\x01\xd8\x43\x03\x3b\x78\xc5\xa9\x17\x0c\x0e\x86\x48\xd8\xba\ +\x42\x23\x20\x3d\x6e\x3e\x20\x57\xf8\x2d\xc6\x97\x13\xa5\xf4\x26\ +\x2f\x03\x90\xeb\x89\x1c\x86\xf5\xf3\x80\x31\xc0\xca\x72\x90\xa4\ +\x44\x47\x26\x34\x0f\x71\x37\x0f\x24\xec\x6d\x65\x60\xd9\x9c\xd9\ +\x6c\x04\xcd\x2a\xd7\x02\xca\xa2\xf5\x7a\xb8\xa8\xeb\x01\xcb\xc6\ +\x79\xb3\x51\x14\xd5\xae\x09\x47\xc6\xf7\x33\x07\x98\x59\xed\x5a\ +\x80\x09\xd3\x0a\xb3\x81\x89\x6a\xd7\x02\x4c\x22\x05\x3c\x1b\xa2\ +\x54\x93\xf2\x60\x25\x0b\xb0\xa7\xb6\x60\x52\x0b\x52\xa9\x45\x2e\ +\xec\x44\x7c\x66\x0e\xa7\x98\x59\xcc\x9e\xcd\xa8\x12\x00\x80\xbe\ +\x33\x6e\x7d\xc3\x4c\x3a\xdf\x8e\x8b\x96\xc1\xc0\xa7\x5e\xc7\xf1\ +\xf0\xd6\x03\xf7\x29\x5e\xb4\x80\xfe\x1c\x53\xaa\x5b\xc0\x86\x88\ +\xf1\xdb\x78\x5f\xa9\xbb\x64\xda\x8d\x59\x13\xd3\xa5\x17\xa8\x0e\ +\xa8\xc1\xd7\xe6\x5a\x87\x59\x9f\x58\x6c\x30\x82\x9f\x6e\xb2\x1a\ +\x09\x7f\x13\x35\x1d\xa3\x91\xa7\xa7\x97\x08\x02\xb7\xef\x3b\x17\ +\x00\xf0\x7d\xf8\x38\xed\x1c\x9d\x5d\xb4\x1b\xd3\x50\x9d\xe1\xdb\ +\x0f\x3b\x72\x19\x7e\x6e\x4e\x9b\xa4\xe9\xde\x8e\x9b\x67\xc9\xee\ +\xce\x9b\x59\xdd\x99\x9f\xd2\x2e\x4d\x02\xb5\x6b\xc5\xf4\xec\xfe\ +\x8c\x6a\x71\x8c\x38\x4d\xe0\xf8\xa8\x0c\x8e\x4f\xce\x9a\xa9\xee\ +\x8e\x2b\xc3\xf1\xf1\xea\x70\x7c\x5a\x2d\x8e\x4f\x93\x84\xd7\x3a\ +\x3b\x5c\x25\x8e\x5b\x67\xad\x0d\xc4\x71\xf8\x5d\x99\x8a\x31\xdb\ +\x5a\x29\x66\x9b\xa7\x6b\xc3\xec\xf2\x12\x22\xbc\x02\xad\x5a\xcc\ +\x9e\x9c\x27\x19\xf9\xf4\xa4\x0c\x66\x8f\x4e\x8e\xb7\x40\xf6\x86\ +\x97\x3c\x55\x8b\xd9\xa3\xa3\x14\x66\xcf\x56\x49\xb3\x55\x62\xf6\ +\xac\xbc\xc4\x8d\x3e\x94\x51\x2d\x92\x9b\x29\xfa\x6d\x5d\x94\x92\ +\x0c\xc7\xe8\x2b\x49\x74\x97\xa9\x26\x37\xc5\x76\x88\x5d\xfa\x59\ +\xb1\xf5\x90\xb6\xd0\x4a\x49\x89\x56\xeb\xf4\x31\xc6\xc8\x7c\x2c\ +\xc7\x1f\xa1\xbe\xdd\x98\xf0\xce\xde\xff\x01\xff\x94\xb5\x4d\ \x00\x00\x07\xb5\ \x00\ \x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\ @@ -47974,6 +47977,304 @@ qt_resource_data = "\ \xd8\xee\x88\x05\x36\x62\x1e\x73\xd8\x05\xd9\xfd\xc8\xa6\x16\xbb\ \x60\xfb\xff\x13\xdb\xc4\xf6\x10\x20\x00\x07\xd7\xda\x76\xd2\xe2\ \xf0\x1a\x0c\x5f\x13\xf5\xb6\x7e\x7b\xf5\x17\x93\x56\xec\x3d\ +\x00\x00\x12\x80\ +\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\x34\ +\x35\x39\x34\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\x44\x72\x61\x66\x74\x5f\ +\x53\x68\x61\x70\x65\x53\x74\x72\x69\x6e\x67\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\x34\x35\x39\x36\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\x34\x36\x30\x32\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\x36\x35\x36\x38\ +\x35\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x78\x3d\x22\x31\x36\x2e\x37\x32\x34\x37\x31\x38\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x79\x3d\x22\x32\x34\x2e\x38\x33\x31\x39\x30\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\x33\x36\x36\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\x36\x39\x35\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\x32\x34\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\x34\x35\x39\x39\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\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\x74\x65\x78\ +\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6d\x6c\x3a\x73\x70\x61\ +\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x6f\x6e\x74\ +\x2d\x73\x69\x7a\x65\x3a\x34\x30\x70\x78\x3b\x66\x6f\x6e\x74\x2d\ +\x73\x74\x79\x6c\x65\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\x66\x6f\x6e\ +\x74\x2d\x77\x65\x69\x67\x68\x74\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\ +\x6c\x69\x6e\x65\x2d\x68\x65\x69\x67\x68\x74\x3a\x31\x32\x35\x25\ +\x3b\x6c\x65\x74\x74\x65\x72\x2d\x73\x70\x61\x63\x69\x6e\x67\x3a\ +\x30\x70\x78\x3b\x77\x6f\x72\x64\x2d\x73\x70\x61\x63\x69\x6e\x67\ +\x3a\x30\x70\x78\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x30\x30\x30\ +\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ +\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x66\x6f\x6e\ +\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x53\x61\x6e\x73\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x35\x2e\x36\x38\x34\x39\ +\x31\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x39\ +\x2e\x37\x37\x33\x36\x38\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x74\x65\x78\x74\x33\x30\x39\x37\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6c\x69\ +\x6e\x65\x73\x70\x61\x63\x69\x6e\x67\x3d\x22\x31\x32\x35\x25\x22\ +\x3e\x3c\x74\x73\x70\x61\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x6f\x6c\x65\x3d\x22\ +\x6c\x69\x6e\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x74\x73\x70\x61\x6e\x33\x30\x39\x39\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x35\x2e\x36\x38\x34\ +\x39\x31\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\ +\x22\x31\x39\x2e\x37\x37\x33\x36\x38\x34\x22\x20\x2f\x3e\x3c\x2f\ +\x74\x65\x78\x74\x3e\x0a\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\x30\x36\x31\x22\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x74\x65\x78\x74\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ +\x73\x63\x61\x6c\x65\x28\x31\x2e\x32\x36\x33\x30\x37\x37\x33\x2c\ +\x30\x2e\x37\x39\x31\x37\x31\x37\x31\x39\x29\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6c\ +\x69\x6e\x65\x73\x70\x61\x63\x69\x6e\x67\x3d\x22\x31\x32\x35\x25\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x74\ +\x65\x78\x74\x33\x38\x39\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x79\x3d\x22\x36\x39\x2e\x35\x30\x38\x33\x38\x35\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x35\x2e\x34\x36\ +\x35\x34\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x66\x6f\x6e\x74\x2d\x73\x69\x7a\x65\x3a\ +\x37\x37\x2e\x33\x39\x35\x34\x36\x32\x30\x33\x39\x39\x39\x39\x39\ +\x39\x38\x31\x38\x70\x78\x3b\x66\x6f\x6e\x74\x2d\x73\x74\x79\x6c\ +\x65\x3a\x69\x74\x61\x6c\x69\x63\x3b\x66\x6f\x6e\x74\x2d\x76\x61\ +\x72\x69\x61\x6e\x74\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\x66\x6f\x6e\ +\x74\x2d\x77\x65\x69\x67\x68\x74\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\ +\x66\x6f\x6e\x74\x2d\x73\x74\x72\x65\x74\x63\x68\x3a\x6e\x6f\x72\ +\x6d\x61\x6c\x3b\x74\x65\x78\x74\x2d\x61\x6c\x69\x67\x6e\x3a\x73\ +\x74\x61\x72\x74\x3b\x6c\x69\x6e\x65\x2d\x68\x65\x69\x67\x68\x74\ +\x3a\x31\x32\x35\x25\x3b\x6c\x65\x74\x74\x65\x72\x2d\x73\x70\x61\ +\x63\x69\x6e\x67\x3a\x30\x70\x78\x3b\x77\x6f\x72\x64\x2d\x73\x70\ +\x61\x63\x69\x6e\x67\x3a\x30\x70\x78\x3b\x77\x72\x69\x74\x69\x6e\ +\x67\x2d\x6d\x6f\x64\x65\x3a\x6c\x72\x2d\x74\x62\x3b\x74\x65\x78\ +\x74\x2d\x61\x6e\x63\x68\x6f\x72\x3a\x73\x74\x61\x72\x74\x3b\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x36\x32\x37\x31\x31\x38\x36\ +\x33\x39\x39\x39\x39\x39\x39\x39\x39\x35\x3b\x63\x6f\x6c\x6f\x72\ +\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x30\ +\x30\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\x6e\ +\x6f\x6e\x7a\x65\x72\x6f\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\x39\x31\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\x3b\x66\x6f\ +\x6e\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x54\x69\x6d\x65\x73\x20\ +\x4e\x65\x77\x20\x52\x6f\x6d\x61\x6e\x3b\x2d\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x2d\x66\x6f\x6e\x74\x2d\x73\x70\x65\x63\x69\x66\x69\ +\x63\x61\x74\x69\x6f\x6e\x3a\x27\x54\x69\x6d\x65\x73\x20\x4e\x65\ +\x77\x20\x52\x6f\x6d\x61\x6e\x2c\x20\x49\x74\x61\x6c\x69\x63\x27\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x6d\x6c\x3a\x73\ +\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\ +\x3c\x74\x73\x70\x61\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3a\x33\x2e\x31\x39\x31\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\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x79\x3d\x22\x36\x39\x2e\x35\x30\x38\x33\x38\x35\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x35\x2e\ +\x34\x36\x35\x34\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x74\x73\x70\x61\x6e\x33\x38\x39\x34\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x72\x6f\x6c\x65\x3d\x22\x6c\x69\x6e\x65\ +\x22\x3e\x53\x3c\x2f\x74\x73\x70\x61\x6e\x3e\x3c\x74\x73\x70\x61\ +\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ +\x3a\x33\x2e\x31\x39\x31\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\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x74\x73\x70\x61\x6e\x33\x38\x39\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x36\x36\x2e\x32\x35\ +\x32\x37\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x78\x3d\x22\x35\x2e\x34\x36\x35\x34\x32\x35\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\ +\x3a\x72\x6f\x6c\x65\x3d\x22\x6c\x69\x6e\x65\x22\x20\x2f\x3e\x3c\ +\x2f\x74\x65\x78\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x74\x65\ +\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x2d\x63\ +\x65\x6e\x74\x65\x72\x2d\x79\x3d\x22\x31\x37\x2e\x36\x34\x36\x37\ +\x39\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x2d\ +\x63\x65\x6e\x74\x65\x72\x2d\x78\x3d\x22\x31\x2e\x39\x38\x35\x39\ +\x39\x32\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\ +\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x73\x63\x61\x6c\x65\x28\x31\ +\x2e\x32\x35\x38\x36\x38\x35\x2c\x30\x2e\x37\x39\x34\x34\x37\x39\ +\x39\x36\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\ +\x64\x69\x70\x6f\x64\x69\x3a\x6c\x69\x6e\x65\x73\x70\x61\x63\x69\ +\x6e\x67\x3d\x22\x31\x32\x35\x25\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x74\x65\x78\x74\x33\x31\x30\x33\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x36\x35\x2e\ +\x32\x32\x35\x36\x33\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x78\x3d\x22\x32\x2e\x31\x37\x37\x34\x36\x36\x39\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\ +\x6f\x6e\x74\x2d\x73\x69\x7a\x65\x3a\x38\x30\x2e\x30\x36\x37\x31\ +\x33\x31\x30\x34\x70\x78\x3b\x66\x6f\x6e\x74\x2d\x73\x74\x79\x6c\ +\x65\x3a\x69\x74\x61\x6c\x69\x63\x3b\x66\x6f\x6e\x74\x2d\x76\x61\ +\x72\x69\x61\x6e\x74\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\x66\x6f\x6e\ +\x74\x2d\x77\x65\x69\x67\x68\x74\x3a\x6e\x6f\x72\x6d\x61\x6c\x3b\ +\x66\x6f\x6e\x74\x2d\x73\x74\x72\x65\x74\x63\x68\x3a\x6e\x6f\x72\ +\x6d\x61\x6c\x3b\x74\x65\x78\x74\x2d\x61\x6c\x69\x67\x6e\x3a\x73\ +\x74\x61\x72\x74\x3b\x6c\x69\x6e\x65\x2d\x68\x65\x69\x67\x68\x74\ +\x3a\x31\x32\x35\x25\x3b\x6c\x65\x74\x74\x65\x72\x2d\x73\x70\x61\ +\x63\x69\x6e\x67\x3a\x30\x70\x78\x3b\x77\x6f\x72\x64\x2d\x73\x70\ +\x61\x63\x69\x6e\x67\x3a\x30\x70\x78\x3b\x77\x72\x69\x74\x69\x6e\ +\x67\x2d\x6d\x6f\x64\x65\x3a\x6c\x72\x2d\x74\x62\x3b\x74\x65\x78\ +\x74\x2d\x61\x6e\x63\x68\x6f\x72\x3a\x73\x74\x61\x72\x74\x3b\x63\ +\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\ +\x6c\x3a\x23\x66\x66\x64\x61\x30\x34\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\x6e\x6f\x6e\x7a\x65\x72\x6f\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\x31\x2e\x35\x37\x33\x33\x33\x31\x35\ +\x39\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\x3b\x66\x6f\x6e\x74\x2d\x66\x61\x6d\x69\ +\x6c\x79\x3a\x54\x69\x6d\x65\x73\x20\x4e\x65\x77\x20\x52\x6f\x6d\ +\x61\x6e\x3b\x2d\x69\x6e\x6b\x73\x63\x61\x70\x65\x2d\x66\x6f\x6e\ +\x74\x2d\x73\x70\x65\x63\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x3a\ +\x27\x54\x69\x6d\x65\x73\x20\x4e\x65\x77\x20\x52\x6f\x6d\x61\x6e\ +\x2c\x20\x49\x74\x61\x6c\x69\x63\x27\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\ +\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x3c\x74\x73\x70\x61\x6e\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x31\ +\x2e\x35\x37\x33\x33\x33\x31\x35\x39\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x36\x35\x2e\x32\x32\x35\x36\ +\x33\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\ +\x3d\x22\x32\x2e\x31\x37\x37\x34\x36\x36\x39\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x74\x73\x70\x61\ +\x6e\x33\x31\x30\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x6f\x6c\x65\x3d\ +\x22\x6c\x69\x6e\x65\x22\x3e\x53\x3c\x2f\x74\x73\x70\x61\x6e\x3e\ +\x3c\x2f\x74\x65\x78\x74\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\x0f\xd2\ \x00\ \x00\x52\x9a\x78\x9c\xe5\x5c\x5b\x6f\xe3\xb8\x15\x7e\x9f\x5f\xa1\ @@ -52990,6 +53291,11 @@ qt_resource_name = "\ \x07\x2c\x24\xc7\ \x00\x53\ \x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x41\x00\x6e\x00\x67\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x15\ +\x03\xf8\x76\x47\ +\x00\x44\ +\x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x53\x00\x68\x00\x61\x00\x70\x00\x65\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\ +\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0d\x13\x54\x07\ \x00\x44\ @@ -53092,8 +53398,8 @@ qt_resource_name = "\ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x58\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x37\x00\x00\x00\x21\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x59\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x38\x00\x00\x00\x21\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x1c\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x17\x00\x00\x00\x05\ \x00\x00\x01\xb4\x00\x01\x00\x00\x00\x01\x00\x04\x04\x86\ @@ -53124,61 +53430,62 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x0a\xf8\x7b\ -\x00\x00\x04\x7c\x00\x00\x00\x00\x00\x01\x00\x0a\x55\x64\ -\x00\x00\x09\x04\x00\x01\x00\x00\x00\x01\x00\x0b\xbc\xed\ -\x00\x00\x0b\x94\x00\x01\x00\x00\x00\x01\x00\x0c\x98\xf8\ -\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x0a\x95\x0f\ -\x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x0b\x15\xc5\ -\x00\x00\x08\x2a\x00\x01\x00\x00\x00\x01\x00\x0b\x7e\x73\ -\x00\x00\x0a\xf6\x00\x01\x00\x00\x00\x01\x00\x0c\x6f\xb5\ -\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x0b\x3f\x94\ -\x00\x00\x09\x9e\x00\x01\x00\x00\x00\x01\x00\x0b\xfd\x8e\ -\x00\x00\x0b\xe4\x00\x01\x00\x00\x00\x01\x00\x0c\xb5\x1c\ -\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x0a\x6e\x86\ -\x00\x00\x08\x50\x00\x01\x00\x00\x00\x01\x00\x0b\x84\x37\ -\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x0b\x03\x2f\ -\x00\x00\x04\xe6\x00\x01\x00\x00\x00\x01\x00\x0a\x74\x05\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x0b\x2e\x8a\ -\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x0a\x64\x1a\ -\x00\x00\x0b\x1e\x00\x00\x00\x00\x00\x01\x00\x0c\x7b\x24\ -\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x0a\x2f\xd2\ -\x00\x00\x05\xd6\x00\x01\x00\x00\x00\x01\x00\x0a\xb0\x2e\ -\x00\x00\x0a\xae\x00\x01\x00\x00\x00\x01\x00\x0c\x58\x86\ -\x00\x00\x0a\xd0\x00\x01\x00\x00\x00\x01\x00\x0c\x66\x21\ -\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x0a\x9e\x15\ -\x00\x00\x03\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x28\x19\ -\x00\x00\x08\xba\x00\x01\x00\x00\x00\x01\x00\x0b\xa5\xc3\ -\x00\x00\x09\xf8\x00\x00\x00\x00\x00\x01\x00\x0c\x0d\xd6\ -\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x0a\xc1\x9e\ -\x00\x00\x0a\x1c\x00\x00\x00\x00\x00\x01\x00\x0c\x24\x89\ -\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x0b\x57\x47\ -\x00\x00\x05\x38\x00\x01\x00\x00\x00\x01\x00\x0a\x84\x05\ -\x00\x00\x0b\xb4\x00\x00\x00\x00\x00\x01\x00\x0c\xa3\xa6\ -\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xd8\xdd\ -\x00\x00\x04\x28\x00\x00\x00\x00\x00\x01\x00\x0a\x37\xd9\ -\x00\x00\x0c\x14\x00\x00\x00\x00\x00\x01\x00\x0c\xc0\xf5\ -\x00\x00\x0a\x64\x00\x00\x00\x00\x00\x01\x00\x0c\x42\x10\ -\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x0a\x4c\xf9\ -\x00\x00\x0a\x8c\x00\x01\x00\x00\x00\x01\x00\x0c\x51\x37\ -\x00\x00\x09\x26\x00\x01\x00\x00\x00\x01\x00\x0b\xc5\x96\ -\x00\x00\x0b\x44\x00\x01\x00\x00\x00\x01\x00\x0c\x83\xb1\ -\x00\x00\x06\xac\x00\x01\x00\x00\x00\x01\x00\x0a\xeb\x1c\ -\x00\x00\x07\xbc\x00\x01\x00\x00\x00\x01\x00\x0b\x4d\x96\ -\x00\x00\x09\x7c\x00\x00\x00\x00\x00\x01\x00\x0b\xe8\xfd\ -\x00\x00\x05\x5c\x00\x01\x00\x00\x00\x01\x00\x0a\x8a\xce\ -\x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x0b\x68\xff\ -\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x0a\xbc\x1f\ -\x00\x00\x09\xc8\x00\x01\x00\x00\x00\x01\x00\x0c\x04\x03\ -\x00\x00\x08\x92\x00\x01\x00\x00\x00\x01\x00\x0b\x9a\x51\ -\x00\x00\x08\xdc\x00\x01\x00\x00\x00\x01\x00\x0b\xad\x17\ -\x00\x00\x0b\x6a\x00\x01\x00\x00\x00\x01\x00\x0c\x8e\x76\ -\x00\x00\x0a\x40\x00\x01\x00\x00\x00\x01\x00\x0c\x37\x60\ -\x00\x00\x05\x08\x00\x01\x00\x00\x00\x01\x00\x0a\x7b\xe3\ -\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0b\x8a\x7f\ -\x00\x00\x06\x58\x00\x00\x00\x00\x00\x01\x00\x0a\xc9\x83\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x0b\x25\x16\ -\x00\x00\x09\x4a\x00\x00\x00\x00\x00\x01\x00\x0b\xcc\xe7\ +\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x0a\xf8\xb6\ +\x00\x00\x04\x7c\x00\x00\x00\x00\x00\x01\x00\x0a\x55\x9f\ +\x00\x00\x09\x34\x00\x01\x00\x00\x00\x01\x00\x0b\xcf\xac\ +\x00\x00\x0b\xc4\x00\x01\x00\x00\x00\x01\x00\x0c\xab\xb7\ +\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x0a\x95\x4a\ +\x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x0b\x16\x00\ +\x00\x00\x08\x2a\x00\x01\x00\x00\x00\x01\x00\x0b\x7e\xae\ +\x00\x00\x0b\x26\x00\x01\x00\x00\x00\x01\x00\x0c\x82\x74\ +\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x0b\x3f\xcf\ +\x00\x00\x09\xce\x00\x01\x00\x00\x00\x01\x00\x0c\x10\x4d\ +\x00\x00\x0c\x14\x00\x01\x00\x00\x00\x01\x00\x0c\xc7\xdb\ +\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x0a\x6e\xc1\ +\x00\x00\x08\xdc\x00\x00\x00\x00\x00\x01\x00\x0b\xad\x52\ +\x00\x00\x08\x50\x00\x01\x00\x00\x00\x01\x00\x0b\x84\x72\ +\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x0b\x03\x6a\ +\x00\x00\x04\xe6\x00\x01\x00\x00\x00\x01\x00\x0a\x74\x40\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x0b\x2e\xc5\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x0a\x64\x55\ +\x00\x00\x0b\x4e\x00\x00\x00\x00\x00\x01\x00\x0c\x8d\xe3\ +\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x0a\x30\x0d\ +\x00\x00\x05\xd6\x00\x01\x00\x00\x00\x01\x00\x0a\xb0\x69\ +\x00\x00\x0a\xde\x00\x01\x00\x00\x00\x01\x00\x0c\x6b\x45\ +\x00\x00\x0b\x00\x00\x01\x00\x00\x00\x01\x00\x0c\x78\xe0\ +\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x0a\x9e\x50\ +\x00\x00\x03\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x28\x54\ +\x00\x00\x08\xba\x00\x01\x00\x00\x00\x01\x00\x0b\xa5\xfe\ +\x00\x00\x0a\x28\x00\x00\x00\x00\x00\x01\x00\x0c\x20\x95\ +\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x0a\xc1\xd9\ +\x00\x00\x0a\x4c\x00\x00\x00\x00\x00\x01\x00\x0c\x37\x48\ +\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x0b\x57\x82\ +\x00\x00\x05\x38\x00\x01\x00\x00\x00\x01\x00\x0a\x84\x40\ +\x00\x00\x0b\xe4\x00\x00\x00\x00\x00\x01\x00\x0c\xb6\x65\ +\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xd9\x18\ +\x00\x00\x04\x28\x00\x00\x00\x00\x00\x01\x00\x0a\x38\x14\ +\x00\x00\x0c\x44\x00\x00\x00\x00\x00\x01\x00\x0c\xd3\xb4\ +\x00\x00\x0a\x94\x00\x00\x00\x00\x00\x01\x00\x0c\x54\xcf\ +\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x0a\x4d\x34\ +\x00\x00\x0a\xbc\x00\x01\x00\x00\x00\x01\x00\x0c\x63\xf6\ +\x00\x00\x09\x56\x00\x01\x00\x00\x00\x01\x00\x0b\xd8\x55\ +\x00\x00\x0b\x74\x00\x01\x00\x00\x00\x01\x00\x0c\x96\x70\ +\x00\x00\x06\xac\x00\x01\x00\x00\x00\x01\x00\x0a\xeb\x57\ +\x00\x00\x07\xbc\x00\x01\x00\x00\x00\x01\x00\x0b\x4d\xd1\ +\x00\x00\x09\xac\x00\x00\x00\x00\x00\x01\x00\x0b\xfb\xbc\ +\x00\x00\x05\x5c\x00\x01\x00\x00\x00\x01\x00\x0a\x8b\x09\ +\x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x0b\x69\x3a\ +\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x0a\xbc\x5a\ +\x00\x00\x09\xf8\x00\x01\x00\x00\x00\x01\x00\x0c\x16\xc2\ +\x00\x00\x08\x92\x00\x01\x00\x00\x00\x01\x00\x0b\x9a\x8c\ +\x00\x00\x09\x0c\x00\x01\x00\x00\x00\x01\x00\x0b\xbf\xd6\ +\x00\x00\x0b\x9a\x00\x01\x00\x00\x00\x01\x00\x0c\xa1\x35\ +\x00\x00\x0a\x70\x00\x01\x00\x00\x00\x01\x00\x0c\x4a\x1f\ +\x00\x00\x05\x08\x00\x01\x00\x00\x00\x01\x00\x0a\x7c\x1e\ +\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0b\x8a\xba\ +\x00\x00\x06\x58\x00\x00\x00\x00\x00\x01\x00\x0a\xc9\xbe\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x0b\x25\x51\ +\x00\x00\x09\x7a\x00\x00\x00\x00\x00\x01\x00\x0b\xdf\xa6\ \x00\x00\x03\x76\x00\x01\x00\x00\x00\x01\x00\x0a\x0d\xd7\ \x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x0a\x17\x90\ " diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 92ab01df7f..eef95a530e 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -104,7 +104,8 @@ class DraftWorkbench (Workbench): pass self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse", "Draft_Polygon","Draft_Rectangle", "Draft_Text", - "Draft_Dimension", "Draft_BSpline","Draft_Point"] + "Draft_Dimension", "Draft_BSpline","Draft_Point", + "Draft_ShapeString"] self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset", "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index d2a211e29b..2ab4498084 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -55,6 +55,7 @@ icons/Draft_Clone.svg icons/Draft_Heal.svg icons/Draft_Ellipse.svg + icons/Draft_ShapeString.svg patterns/concrete.svg patterns/cross.svg patterns/line.svg diff --git a/src/Mod/Draft/Resources/icons/Draft_ShapeString.svg b/src/Mod/Draft/Resources/icons/Draft_ShapeString.svg new file mode 100644 index 0000000000..53b09f83cd --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Draft_ShapeString.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + S + S + + + diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui index d64f95ecdb..f373dda63f 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-base.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui @@ -6,8 +6,8 @@ 0 0 - 590 - 632 + 718 + 808 @@ -1199,6 +1199,49 @@ such as "Arial:Bold" + + + + + + Default ShapeString Font File + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 300 + 0 + + + + Select a font file + + + FontFile + + + Mod/Draft + + + + + From 8eff656ae1d5be4cf65d6f774c52099b5f2f951b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 17 Apr 2013 11:16:06 -0300 Subject: [PATCH 16/53] 0001046: Draft angular dimensions --- src/Mod/Draft/DraftSnap.py | 9 +++++---- src/Mod/Draft/DraftTools.py | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 58ee1d06be..bedb71f13b 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -104,13 +104,14 @@ class Snapper: 'ortho':':/icons/Snap_Ortho.svg', 'intersection':':/icons/Snap_Intersection.svg'} - def snap(self,screenpos,lastpoint=None,active=True,constrain=False): - """snap(screenpos,lastpoint=None,active=True,constrain=False): returns a snapped + def snap(self,screenpos,lastpoint=None,active=True,constrain=False,noTracker=False): + """snap(screenpos,lastpoint=None,active=True,constrain=False,noTracker=False): returns a snapped point from the given (x,y) screenpos (the position of the mouse cursor), active is to activate active point snapping or not (passive), lastpoint is an optional other point used to draw an imaginary segment and get additional snap locations. Constrain can be True to constrain the point against the closest working plane axis. - Screenpos can be a list, a tuple or a coin.SbVec2s object.""" + Screenpos can be a list, a tuple or a coin.SbVec2s object. If noTracker is True, + the tracking line is not displayed.""" global Part, DraftGeomUtils import Part, DraftGeomUtils @@ -196,7 +197,7 @@ class Snapper: if active: point = self.snapToGrid(point) fp = cstr(point) - if self.trackLine and lastpoint: + if self.trackLine and lastpoint and (not noTracker): self.trackLine.p2(fp) self.trackLine.on() return fp diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index da6d5e53d1..5d870e2203 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -121,14 +121,15 @@ def selectObject(arg): FreeCAD.activeDraftCommand.component=snapped['Component'] FreeCAD.activeDraftCommand.proceed() -def getPoint(target,args,mobile=False,sym=False,workingplane=True): +def getPoint(target,args,mobile=False,sym=False,workingplane=True,noTracker=False): ''' Function used by the Draft Tools. returns a constrained 3d point and its original point. if mobile=True, the constraining occurs from the location of mouse cursor when Shift is pressed, otherwise from last entered point. If sym=True, x and y values stay always equal. If workingplane=False, - the point wont be projected on the Working Plane. + the point wont be projected on the Working Plane. if noTracker is True, the + tracking line will not be displayed ''' ui = FreeCADGui.draftToolBar @@ -141,7 +142,7 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True): last = None amod = hasMod(args,MODSNAP) cmod = hasMod(args,MODCONSTRAIN) - point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod) + point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod,noTracker=noTracker) info = FreeCADGui.Snapper.snapInfo ctrlPoint = Vector(point) mask = FreeCADGui.Snapper.affinity @@ -606,7 +607,7 @@ class BSpline(Line): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - self.point,ctrlPoint,info = getPoint(self,arg) + self.point,ctrlPoint,info = getPoint(self,arg,noTracker=True) self.bsplinetrack.update(self.node + [self.point]) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): @@ -813,7 +814,7 @@ class Rectangle(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - self.point,ctrlPoint,info = getPoint(self,arg,mobile=True) + self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True) self.rect.update(self.point) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): @@ -1405,7 +1406,7 @@ class Ellipse(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - self.point,ctrlPoint,info = getPoint(self,arg,mobile=True) + self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True) self.rect.update(self.point) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): @@ -1616,8 +1617,9 @@ class Dimension(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection + import DraftGeomUtils shift = hasMod(arg,MODCONSTRAIN) - self.point,ctrlPoint,self.info = getPoint(self,arg) + self.point,ctrlPoint,self.info = getPoint(self,arg,noTracker=(len(self.node)>0)) if self.arcmode or self.point2: setMod(arg,MODCONSTRAIN,False) if hasMod(arg,MODALT) and (len(self.node)<3): @@ -1696,6 +1698,7 @@ class Dimension(Creator): self.dimtrack.update(self.node+[self.point]+[self.cont]) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + import DraftGeomUtils if self.point: if (not self.node) and (not self.support): self.support = getSupport(arg) @@ -1721,7 +1724,6 @@ class Dimension(Creator): self.node = [v1,v2] self.link = [ob,i1,i2] self.edges.append(ed) - import DraftGeomUtils if DraftGeomUtils.geomType(ed) == "Circle": # snapped edge is an arc self.arcmode = "diameter" @@ -1736,6 +1738,7 @@ class Dimension(Creator): self.node[3], True,True) if c: + print "centers:",c self.center = c[0] self.arctrack.setCenter(self.center) self.arctrack.on() From 1f9fe97b28ef20fcf0f8ec62059d84cba954ec10 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 17 Apr 2013 11:31:43 -0300 Subject: [PATCH 17/53] Updated links in README --- README | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/README b/README index 8ecbded40b..b9a2d2f612 100644 --- a/README +++ b/README @@ -12,13 +12,20 @@ FreeCAD is based on OpenCasCade, a powerful geometry kernel, features an Open In The interface is built with Qt. FreeCAD runs exactly the same way on Windows, Mac OSX, BSD and Linux platforms. -Home page and wiki documentation: http://free-cad.sf.net +Home page: http://www.freecadweb.org +Documentation wiki: http://www.freecadweb.org/wiki Forum: http://sourceforge.net/apps/phpbb/free-cad/ Bug tracker: http://sourceforge.net/apps/mantisbt/free-cad/ -Official git link: git://free-cad.git.sourceforge.net/free-cad/free-cad +Git repository: http://sourceforge.net/p/free-cad/code/ci/master/tree/ -Building -======== +Installing +========== + +Precompiled (installable) packages are usually available to you from several sources and are +described on the FreeCAD download page: http://www.freecadweb.org/wiki/index.php?title=Download + +Compiling +========= Compiling FreeCAD requires to install several heavyweight libraries and their development files such as OpenCasCADe, Coin and Qt, listed in the pages below. Once this is done, @@ -31,12 +38,26 @@ Note that autotools build system can still be used but will be obsoleted soon. The pages below contain up-to-date build instructions: -For Linux: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnUnix -For windows: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnWindows -For Mac OSX: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnMac +For Linux: http://www.freecadweb.org/wiki/index.php?title=CompileOnUnix +For windows: http://www.freecadweb.org/wiki/index.php?title=CompileOnWindows +For Mac OSX: http://www.freecadweb.org/wiki/index.php?title=CompileOnMac In this folder you will also find additional README files, specific for each platform. +Usage +===== + +The FreeCAD documentation wiki contains sections for each category of users, and a manual, +which is a compilation of the most useful articles of the wiki: + +For users: General FreeCAD usage: http://www.freecadweb.org/wiki/index.php?title=User_hub +For power-users: Python scripting: http://www.freecadweb.org/wiki/index.php?title=Power_users_hub +For developers: C++ FreeCAD development: http://www.freecadweb.org/wiki/index.php?title=Developer_hub + +The FreeCAD manual: http://www.freecadweb.org/wiki/index.php?title=Online_Help_Toc + + + From 4ed87cfba4271a395d2b998711a9c7abe11de79a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 17 Apr 2013 14:22:01 -0300 Subject: [PATCH 18/53] 0001057: Bug in Draft Edit --- src/Mod/Draft/DraftTools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 5d870e2203..9ff250aa1e 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3087,7 +3087,8 @@ class Edit(Modifier): Modifier.finish(self) plane.restore() self.running = False - FreeCADGui.ActiveDocument.resetEdit() + # following line causes crash + # FreeCADGui.ActiveDocument.resetEdit() def action(self,arg): "scene event handler" From a1b7dcf7e8c33237d3cd80045d5d7cf12c0daf90 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 17 Apr 2013 17:47:42 -0300 Subject: [PATCH 19/53] 0000729: Arch grouping --- src/Mod/Arch/ArchCommands.py | 7 +- src/Mod/Arch/ArchWall.py | 4 + src/Mod/Arch/Arch_rc.py | 225 ++++++++-- src/Mod/Arch/Resources/Arch.qrc | 1 + .../icons/Arch_Wall_Tree_Assembly.svg | 415 ++++++++++++++++++ 5 files changed, 619 insertions(+), 33 deletions(-) create mode 100644 src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 63b5055b6a..52cf963970 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -165,6 +165,9 @@ def removeComponents(objectsList,host=None): s.remove(o) h.Subtractions = s o.ViewObject.show() + elif o == s.Base: + s.Base = None + o.ViewObject.show() elif tp in ["SectionPlane"]: a = h.Objects if o in a: @@ -569,7 +572,7 @@ class _CommandRemove: def Activated(self): sel = FreeCADGui.Selection.getSelection() FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping"))) - if Draft.getType(sel[-1]) in ["Wall","Structure"]: + if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1): host = sel.pop() ss = "[" for o in sel: @@ -581,7 +584,7 @@ class _CommandRemove: FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") else: FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.removeComponents("+ss+")") + FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 5af1c7481d..e4a7f4bb72 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -472,6 +472,10 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent): def getIcon(self): import Arch_rc + if hasattr(self,"Object"): + for o in self.Object.OutList: + if Draft.getType(o) == "Wall": + return ":/icons/Arch_Wall_Tree_Assembly.svg" return ":/icons/Arch_Wall_Tree.svg" def getDisplayModes(self,vobj): diff --git a/src/Mod/Arch/Arch_rc.py b/src/Mod/Arch/Arch_rc.py index ea96da63c9..2bc77e48c5 100644 --- a/src/Mod/Arch/Arch_rc.py +++ b/src/Mod/Arch/Arch_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Sun Mar 24 15:50:46 2013 +# Created: Wed Apr 17 16:59:58 2013 # by: The Resource Compiler for PyQt (Qt v4.8.2) # # WARNING! All changes made in this file will be lost! @@ -27968,6 +27968,163 @@ qt_resource_data = "\ \xba\x70\x69\x20\x5a\xa2\xbd\xe0\xab\x69\x8b\x99\x5e\x5b\x43\xe6\ \xc8\x70\xb7\x67\xbb\xbc\x3a\xbb\x70\x5b\x40\x57\x67\xff\x01\xbd\ \xf5\xc0\x77\ +\x00\x00\x09\xaf\ +\x00\ +\x00\x5c\xa6\x78\x9c\xed\x5c\x6d\x6f\xdb\x38\x12\xfe\x9e\x5f\xa1\ +\x73\xbf\xec\xe2\x2c\x9a\xef\x2f\x6e\x92\xc5\xe1\x8a\x05\x16\xb8\ +\xfb\xb2\xdb\xc3\x7e\x2c\x64\x89\x76\xb4\x95\x25\x43\x92\xe3\xa4\ +\xbf\xfe\x86\xb2\x2c\x4b\xb6\xeb\xa4\x75\x92\x26\x6b\xb9\x48\x13\ +\x91\x43\x8a\x1c\x3e\x9c\x79\x66\xc8\xe4\xf2\x97\xbb\x79\xe2\xdd\ +\xda\xbc\x88\xb3\xf4\x6a\x40\x10\x1e\x78\x36\x0d\xb3\x28\x4e\x67\ +\x57\x83\xff\x7d\xfc\xd5\xd7\x03\xaf\x28\x83\x34\x0a\x92\x2c\xb5\ +\x57\x83\x34\x1b\xfc\x72\x7d\x71\xf9\x0f\xdf\xf7\xfe\x9d\xdb\xa0\ +\xb4\x91\xb7\x8a\xcb\x1b\xef\xb7\xf4\x73\x11\x06\x0b\xeb\xfd\x74\ +\x53\x96\x8b\xf1\x68\xb4\x5a\xad\x50\x5c\x17\xa2\x2c\x9f\x8d\x7e\ +\xf6\x7c\xff\xfa\xe2\xe2\xb2\xb8\x9d\x5d\x78\x9e\x07\xef\x4d\x8b\ +\x71\x14\x5e\x0d\xea\x06\x8b\x65\x9e\x54\x82\x51\x38\xb2\x89\x9d\ +\xdb\xb4\x2c\x46\x04\x91\xd1\x60\x2b\x1e\x6e\xc5\x43\xf7\xf6\xf8\ +\xd6\x86\xd9\x7c\x9e\xa5\x45\xd5\x32\x2d\xde\xb5\x84\xf3\x68\xda\ +\x48\xbb\xd1\xac\x58\x25\x44\x8c\x31\x23\x4c\x47\x94\xfa\x20\xe1\ +\x17\xf7\x69\x19\xdc\xf9\xdd\xa6\x30\xc6\x43\x4d\x29\xc6\x78\x04\ +\x75\x5b\xc9\xc7\x49\x8d\x0b\x50\xe8\x02\xbe\x1a\xf1\x4d\x01\x2a\ +\xb2\x65\x1e\xda\x29\xb4\xb3\x28\xb5\xe5\xe8\xc3\xc7\x0f\x4d\xa5\ +\x8f\x51\x54\x46\xad\x6e\x36\xfa\xec\xbc\xb5\xa3\xe4\x34\x98\xdb\ +\x62\x11\x84\xb6\x18\x6d\xca\xab\xf6\xab\x38\x2a\x6f\xae\x06\x92\ +\x2f\xee\xaa\xe7\x1b\x1b\xcf\x6e\xca\x56\x41\x1c\x5d\x0d\x60\xcc\ +\x54\x13\x59\x3d\xb7\x20\x41\xd6\x02\x75\x77\xe3\xa6\x06\x23\xae\ +\x11\x43\xc4\xcb\x8d\xd6\xeb\x56\x9b\x91\x8f\xa3\x2c\x74\x43\xb9\ +\x1a\xfc\x2b\x0f\x6f\x3e\xfd\x19\x24\xc9\xa7\x8f\xb9\xb5\xc8\xa9\ +\xe5\x1a\x24\x2f\x23\x3b\x2d\x5c\x8b\xf5\x9b\xdd\x13\xbc\x5a\x57\ +\x75\x50\xdb\xbc\x6c\x01\x2f\x5b\xd8\xd0\x2d\xf4\x5a\xba\xf5\x8e\ +\xf2\xde\x69\xa2\x2b\xca\xd6\xea\xf2\x3a\x03\x5e\x7c\xba\x83\xd1\ +\x7a\x63\x8f\x51\xf8\x8f\x1c\x94\xb8\x5f\x4b\x10\x58\x3b\xf8\x86\ +\x0f\xca\x7c\x71\xfa\x3a\xd2\x4d\x3d\x02\x3f\xcb\xe3\x59\x0c\x0a\ +\xaa\xe4\x28\x41\xac\xfa\x74\xdb\xc0\xa4\x5b\x73\xa3\x9a\xf2\x81\ +\x37\x7a\xc4\xec\x77\x1a\x32\x49\xe9\xc3\x03\xc1\x48\xb8\x49\xd5\ +\x03\xd9\x1d\x4a\x77\x86\xa4\x92\x14\x27\x29\xaa\x56\xf7\x6e\x37\ +\x0f\xad\xdc\xf7\x2a\xc0\x37\x67\xae\x02\xc1\xce\x5c\x01\x4a\x9c\ +\xb9\x02\x8c\x3a\x6f\x05\x28\x7a\x60\x0c\x67\xa5\x00\x7e\xe6\x7e\ +\x40\x49\x7e\xe6\x0a\xd0\x67\x6e\x04\x35\x96\x67\xaf\x00\xff\xcc\ +\x99\x80\x66\x7f\xb7\x4d\x70\x39\x72\xc1\x51\xf5\x53\xd3\xc0\x85\ +\x56\xd1\x6d\x6c\x57\xdb\x08\x6a\x12\x14\xb6\xee\x79\x11\xcc\x20\ +\x2a\x4e\xb2\xfc\x6a\xf0\x6e\x5a\x7d\xea\x8a\x49\x96\x47\x36\xdf\ +\x54\xc9\xea\xd3\xa9\xca\x20\x72\x8c\xcb\xfb\x75\x1e\xe0\x62\x47\ +\x89\xd0\x6b\x53\x8f\x0f\xd7\x17\x37\x41\x94\xad\xae\x06\x74\xb7\ +\xf2\x4b\x96\xcd\xa1\x57\xb2\x5b\x1e\x82\x6a\x88\x44\x04\x2b\x2e\ +\xcc\x5e\x25\xbc\x88\x31\x44\x89\x62\x8d\x69\xdb\x56\x2e\xf3\xdc\ +\xa6\xa5\x9f\x04\xf7\x16\x66\x53\x7d\xdb\x74\x5f\xdc\x64\xab\x59\ +\xee\xb4\x52\xe6\x4b\xbb\xdb\x12\x42\xd3\xa5\x4b\x2e\xf8\xcb\x34\ +\x2e\x21\x80\xaf\x03\xe0\x96\x84\x6b\xeb\x4f\x26\xd9\xdd\xe1\x0e\ +\x8a\x34\x58\x1c\xa9\x76\x35\xfe\x22\x28\x6f\x8a\x23\xf5\x69\x16\ +\xd9\xaf\xd4\x37\xdd\xfb\x36\x9a\x59\x7f\x1e\x47\x8b\x2c\x4e\xcb\ +\x07\xa5\x1f\x10\xcc\x26\x7f\xc1\x1e\x39\x36\xb0\x5a\xe2\xc8\xd0\ +\x56\x71\x0a\xeb\xeb\xd7\xc9\x04\x62\xe8\x1e\x0a\x6a\x89\x4d\x7a\ +\x81\x60\xa1\xbe\x22\xe2\x36\xc5\x57\xaa\xee\xbf\x5e\x35\x0f\xee\ +\xe2\x79\xfc\xc5\xc2\xda\xee\x81\xa9\x52\x45\x3d\xfa\x69\x90\x14\ +\x87\x75\x35\x4b\xb2\x49\x90\x6c\x24\xea\x3d\x36\xb7\x65\x10\x05\ +\x65\xb0\xdd\x4f\x9b\x12\x88\xcc\xc9\x26\x2b\x91\x47\xd3\xf1\xef\ +\x1f\x7e\xbd\xae\x37\xf0\x65\x18\x8e\xff\xcc\xf2\xcf\x9b\xfd\xec\ +\x79\x4e\x20\x98\x64\x4b\x98\xf9\xe0\xba\x29\xbe\x8c\xc2\xf1\x34\ +\xcb\xe7\x41\x79\x1d\xcf\x61\x97\xb8\xdc\xd0\x3f\xef\xe6\x09\xec\ +\xec\xa6\xa2\x23\xec\xec\xc1\xb6\xd3\x75\xb7\xb9\x5d\x67\x8a\x0e\ +\xa6\xcb\xa2\x70\x1e\xbb\x46\xa3\x3f\xca\x38\x49\x7e\x73\x2f\x69\ +\xcc\x67\xd3\x69\x5c\x26\xf6\xba\x7a\xe7\xfa\xc7\xcd\x2c\x46\xf5\ +\x34\xea\x49\x8e\x5a\xb3\xbc\x1c\x6d\xd4\x50\x3d\xcd\xb6\xea\xe9\ +\xec\xb7\x46\xc1\x49\x30\xb1\xa0\xda\xff\xb8\x4a\x6f\xaf\x76\x96\ +\x67\xcb\xc5\x1c\xd6\xa7\x6e\xde\xa8\x15\x50\xd7\xd8\xc4\xf2\x3e\ +\x81\xfa\xca\x46\x8d\xdf\xe1\xea\xf3\x7e\x0a\x93\x1a\xbf\x53\x81\ +\xfb\x57\x3d\xf8\xb5\x21\x1a\x93\xf5\x63\xbe\x4c\xec\xd8\xde\x5a\ +\x58\xfc\xe8\x7d\x51\xe6\xd9\x67\xdb\x34\x5e\x3f\xae\x31\x3b\x26\ +\xc8\x68\x0a\x56\x8f\x8a\x4d\x79\x12\xa7\x16\x46\x37\x9e\x2c\xcb\ +\xb2\x5d\xf6\x17\x6c\xa5\x31\x0c\x38\xdd\x74\x08\xfb\xab\xb4\x79\ +\x02\xe8\x2b\xc7\x7c\x53\xb6\x1d\x47\x5d\x10\x05\x60\x03\xf3\x3c\ +\xb8\x1f\xa7\x59\x6a\xdb\xa5\xd9\x74\x5a\xd8\x72\x8c\xdf\xcf\x83\ +\xfc\xb3\xcd\xd7\xf5\xb7\x71\x11\x4f\xe2\xc4\x75\x51\xfd\x98\xd8\ +\xf7\x51\x5c\x2c\x40\x3d\xe3\x38\x75\xc3\x78\x9f\xdd\xda\x7c\x9a\ +\x64\xab\xa6\xde\xa6\x01\x7c\xf3\x27\x41\xf8\x79\x56\x8d\x6f\x1c\ +\x84\x60\xd0\x96\x49\x50\xda\xad\xf7\x81\x25\x72\x6a\xa5\x9a\x63\ +\x9f\xf9\xdc\xc7\xbe\xf6\xb7\x9e\xb1\xde\xc0\x1a\x69\x23\x0d\xa3\ +\x5b\xda\xd4\xa4\x05\x11\x27\x42\x6a\xbc\xa5\xd4\xb0\x5d\x05\x58\ +\x7d\x8a\x25\xd1\x4d\x21\x6c\x54\x8d\x91\x26\x9a\xc8\x6d\x0a\xa6\ +\xcc\x83\xb4\x70\xb0\x86\x4d\x14\x94\x79\x7c\xf7\x13\x88\x60\x86\ +\x15\x36\x72\xe8\x83\x13\x34\x42\x6b\xc6\xc9\x10\x0f\xdd\x17\xfe\ +\x79\xeb\xe9\x1f\x89\x84\xb5\x53\x3b\x15\x09\x1a\xe6\xc2\x89\x31\ +\x67\x84\x04\xb5\x8b\x00\xc2\x11\xd1\x9a\x72\x7d\x00\x01\x4c\x02\ +\x32\x74\x07\x01\x54\x21\x63\x08\x26\xac\x8d\x00\xa6\x11\xc5\x84\ +\x6a\x79\x14\x01\x46\x50\x26\x25\x83\x15\x47\x0c\x73\x23\x24\xef\ +\xd7\xff\xc5\xd7\xdf\xf8\xf2\x44\x04\x70\x86\x04\xa1\x42\xec\x00\ +\x80\x18\x00\x05\x3d\x1d\x00\x8e\x9d\x3c\x02\x00\xa1\x72\xff\x4e\ +\x05\x80\x52\x52\x09\x82\xf9\xdf\x1b\x00\x8e\xcb\x78\x40\xa3\x35\ +\xa6\x42\x8a\x21\x27\x88\x33\xa1\x0c\xf3\x48\xb5\x94\x1c\x9b\x21\ +\x47\xb0\xce\xca\x48\xcf\x57\x88\x70\xae\xa5\x1e\x0a\x58\x24\x22\ +\x98\xf0\xfc\xad\x98\x5f\xcb\x29\xaf\x11\xf3\x6b\x39\xee\x7d\xf9\ +\x9a\xef\x11\xd5\xd7\x36\x30\xda\x06\x31\xc0\x04\x1c\x69\x01\xb6\ +\x16\xba\xcf\x7e\xe8\x14\x66\x29\xac\x48\x99\xe5\x3e\xb0\xfd\xdb\ +\xa0\x5c\xe6\xd6\x31\xc3\x1e\x2d\xcf\x8c\x16\xae\x91\xd0\x5c\x09\ +\x40\x8b\x8b\xcd\x84\x24\x7c\x1f\x2d\x6a\x1f\x2d\xfc\x69\xd0\xf2\ +\x2c\x58\xe9\x49\xe6\x4b\x90\x4c\xb1\xef\x60\xbe\x91\x64\x82\x7d\ +\x32\xc2\x28\x61\xda\x1e\x46\x3a\x5f\x24\x31\x16\x3d\xc9\x7c\x0b\ +\x48\xa0\x27\x92\x0c\xa6\x10\xc6\x5c\xd1\x2e\xcd\x84\x45\x65\x4c\ +\x60\xf6\x62\x34\xb3\xb7\x05\x27\xd8\x82\x53\x83\x4d\xa9\x11\xa7\ +\x4a\xea\x8e\x1d\x30\x12\x09\xac\xb5\x7c\x49\x3b\xd0\xa3\xe0\x24\ +\x8f\xb0\x17\x72\x7e\x2b\x0e\x30\x52\x04\xe3\x8e\x29\xd0\x14\x81\ +\xc9\x68\x1f\xf7\x9c\x00\x83\x9e\x44\x3e\x13\x89\xa4\x88\x69\x69\ +\x88\x19\x32\x58\x58\xc9\x99\xa6\xc7\x48\xa4\x7a\x1c\x89\x54\x8f\ +\x23\x91\xf4\xb9\xc3\x8d\x87\x1a\xf5\x88\x7a\x96\x20\xd6\x70\xc1\ +\xb4\x1a\xba\x70\x16\x48\x95\x22\x9e\x74\xd6\x84\x70\x39\x04\x93\ +\xc0\x09\x93\xe6\x60\x54\xd2\x48\xf9\xb5\x98\x3e\x06\x1e\xee\x1f\ +\x38\xa3\xdb\x83\x4f\xcf\x27\x5f\xcc\x8f\xec\xc5\x14\x1c\xc1\xfa\ +\x6a\xd1\xba\xf1\xd1\xe2\x93\x4a\x77\x2e\x45\xba\xc4\x35\x45\x0a\ +\x53\x2e\xd4\x0e\x9f\x94\x94\x51\x72\x3c\x71\xdd\xf3\xc9\x57\x81\ +\x80\x2a\xb6\x3c\x9d\x51\x52\x05\x9b\xbf\xc3\x28\x35\x74\x42\x25\ +\x7e\x1a\x46\xd9\x3b\x88\x1f\xeb\x20\x84\x42\x0c\x5c\x00\xe1\x2e\ +\xcb\x09\x7e\x42\x48\xe9\x71\x24\xa1\x88\xb1\x21\x41\xe0\x3b\x04\ +\x3f\xe8\x1f\x6a\x21\x3e\xf4\xd7\x52\xcc\x1c\xf5\x0f\xdf\xe2\x1d\ +\x7a\x4c\xfc\x60\xd2\x40\x91\x10\x8a\x4a\x3a\x24\xb0\xb6\xc0\x1f\ +\x04\xf1\x0c\xa2\x58\x70\xe0\x11\xe0\x17\x60\x51\x09\x90\x06\x42\ +\x11\x81\x7d\x6d\xd4\x50\x23\x77\x96\x01\x52\x7e\x23\xe6\x37\x72\ +\x47\xf3\x96\xa4\x75\xf9\xea\xe9\x78\x43\xef\x35\x4e\xf1\x1a\xc0\ +\xe5\x60\x6d\xc8\xae\xeb\x20\x02\x61\x89\xdb\x8c\x60\xe3\x3a\x34\ +\xe0\xc0\x18\xae\xba\x27\xdf\xcc\x79\x7f\x21\x3a\x27\xdf\x92\x23\ +\xc1\x01\x28\x7d\x2e\xe2\x4d\x61\x81\x9f\x88\x05\x2e\x20\x9a\xc5\ +\x58\x76\xb0\x20\xa0\x0f\xae\x0c\xe5\x3d\x18\xde\x0e\x18\x4e\x04\ +\x02\x83\xa8\x52\xb2\x4e\x62\x0a\xb0\x01\x51\x26\xe1\x7d\x7e\xf2\ +\xad\xc0\xc0\xd7\x27\x67\x28\xb9\x41\x46\x61\x4e\x3b\x77\x22\xa4\ +\x40\x82\x11\xfa\xa2\x99\xea\x3e\xc3\xf0\x9d\x48\x38\xf5\xbc\xca\ +\x5d\x8b\x72\x11\x45\x07\x01\x94\x22\x03\xc4\x13\xbf\x5c\x7e\xa1\ +\x5f\xff\xef\xbe\x16\x75\x2a\x02\x38\x43\x5c\x61\xda\x4a\x3b\xd5\ +\x08\x00\xaa\x20\x9e\xe0\xc4\xb2\x8f\x22\x7f\x78\xea\x59\x49\x4a\ +\x05\x1f\x52\x89\x88\xd2\x60\xb8\x1f\x75\x23\x66\x7b\x7f\x8a\xec\ +\x9f\x65\x98\xe6\x2c\x43\x3c\x74\x7d\xea\x9b\x12\xd2\x3d\x58\x7e\ +\xf0\xc9\x97\x86\xc0\x10\x3e\x6c\xc8\xc0\xc5\xc3\x42\xd3\xa3\xd7\ +\xa7\xd4\xe3\x2e\xdb\xa9\xc7\xa2\xe5\x39\x0e\x2f\x7a\x92\x79\x52\ +\xac\x71\x7a\xe6\x9a\x29\x05\xbe\xa1\x93\xb9\x26\x88\x52\xd2\xfa\ +\xbd\xef\x9e\x60\xbe\x5a\x14\xd0\x93\x6f\xde\xbb\xfc\x24\x66\x86\ +\xef\x51\x4c\xa0\x0e\x54\xf7\x04\xe3\x0d\x23\xa5\xf2\x19\x44\x23\ +\xa9\x80\x60\xa8\xa1\xfb\x7b\x31\x42\x18\xa9\x5f\x96\x60\xb4\x8e\ +\xd7\xfa\x33\xef\xd7\x60\x30\x0e\x9d\x77\x12\xc5\x05\x69\xb9\x81\ +\xad\xc9\x70\x8b\xac\xb8\x6a\x9b\x0c\xea\xd2\x53\x94\x28\xd9\x31\ +\x19\xcc\x41\xc3\xe8\x3e\x26\x79\xcb\x58\x59\x9b\x0c\x8c\x20\xb6\ +\x14\x44\x0f\xc1\x78\x30\x41\x9d\xc9\x50\x48\x62\xc6\x88\x19\x52\ +\x77\x51\x52\x12\x71\xd0\x62\xac\xa5\x28\x26\xee\x64\xab\x96\x7b\ +\xd8\x3e\xf4\xb7\x62\x5e\x93\x85\x60\x60\x23\x0e\x65\xb0\x15\x11\ +\x10\x7c\x1c\xb0\x10\x50\x21\x0d\x21\x1d\x52\x61\x10\x15\x44\x31\ +\xde\xb6\x10\x10\xb3\x30\x6a\xf8\x53\x58\x88\x1e\x03\xcf\x8f\x81\ +\xfd\x5f\xe8\x13\xee\xef\x5a\x28\x7a\x00\x02\x40\x2b\x78\x3b\x1d\ +\xb5\x76\x12\x20\x8d\xb1\xde\x81\x80\xd6\x44\xf3\xe3\xa7\x59\x3d\ +\x04\x5e\x01\x04\x54\xeb\xce\xc1\x77\x47\x16\x60\x18\x34\xe9\x1a\ +\x01\x77\x57\x4a\x52\xd9\x23\xe0\xd5\x23\xa0\xa2\x8a\xfb\x09\x6c\ +\x83\x08\x35\x58\x99\x7d\x14\x08\xa4\x09\xb0\x06\x46\xbb\x76\x40\ +\x1a\x4c\x88\x22\x3b\x28\xd0\x8c\x4b\xfc\xc4\xbf\xd8\xdb\x93\xc5\ +\x97\x26\x8b\xff\xf5\x38\x30\x03\xa9\x18\xa6\x43\x82\xa4\x06\x2e\ +\x60\x84\x27\x38\x32\x8a\x2a\xed\xe2\x4b\xae\x60\xf1\xb5\x74\xb7\ +\xf6\x35\x61\xda\x80\x1c\x43\xe0\x45\x04\x73\xb9\x6f\x89\x01\x69\ +\x7c\x08\x8c\x53\x68\x2d\x08\x79\xf0\x1e\x54\x7f\x13\xea\x35\x99\ +\x88\xed\xed\x97\x27\xb8\x07\x45\xa8\xc2\x9d\x90\xb2\xba\xf4\x80\ +\xa5\x3e\x6e\x25\xfa\x4b\x0f\xaf\x0c\x0a\xfb\x29\x49\x09\xe6\x40\ +\xb8\x7b\x8e\x07\xc0\xc0\xb5\xc0\x82\x76\xa2\x07\xe9\xee\xd8\x1a\ +\xa2\x3a\xf7\xa9\xc1\xa6\x28\x0c\x2e\xe3\xf4\x5b\x71\x97\xa3\xd9\ +\xf5\xc5\xa5\xfb\x5b\x49\xd7\x17\xff\x07\x1e\x03\x47\xa2\ \x00\x00\x08\x6a\ \x00\ \x00\x47\x9a\x78\x9c\xed\x5a\xdd\x6f\xe3\x36\x12\x7f\xcf\x5f\xa1\ @@ -33045,6 +33202,11 @@ qt_resource_name = "\ \x00\x41\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x43\x00\x65\x00\x6c\x00\x6c\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\x00\x76\ \x00\x67\ +\x00\x1b\ +\x08\x25\x0d\x47\ +\x00\x41\ +\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x57\x00\x61\x00\x6c\x00\x6c\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x5f\x00\x41\x00\x73\ +\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x0d\ \x09\x3c\x92\x47\ \x00\x41\ @@ -33179,8 +33341,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\x39\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x1b\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x3a\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1f\x00\x00\x00\x1b\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x17\x00\x00\x00\x04\ \x00\x00\x01\x2e\x00\x00\x00\x00\x00\x01\x00\x02\x9d\x23\ \x00\x00\x02\x92\x00\x00\x00\x00\x00\x01\x00\x06\x6c\x9e\ @@ -33205,35 +33367,36 @@ qt_resource_struct = "\ \x00\x00\x01\x14\x00\x00\x00\x00\x00\x01\x00\x02\x52\xbc\ \x00\x00\x00\xe0\x00\x00\x00\x00\x00\x01\x00\x01\xbc\xaa\ \x00\x00\x02\x3e\x00\x00\x00\x00\x00\x01\x00\x05\x84\xf1\ -\x00\x00\x06\x5a\x00\x01\x00\x00\x00\x01\x00\x07\xa2\x92\ -\x00\x00\x05\x3a\x00\x00\x00\x00\x00\x01\x00\x07\x59\x96\ -\x00\x00\x03\xd6\x00\x00\x00\x00\x00\x01\x00\x06\xfb\x9a\ -\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\xfa\x67\ -\x00\x00\x06\x2c\x00\x01\x00\x00\x00\x01\x00\x07\x9b\xbd\ -\x00\x00\x04\x10\x00\x01\x00\x00\x00\x01\x00\x07\x0a\x09\ -\x00\x00\x04\x62\x00\x01\x00\x00\x00\x01\x00\x07\x1d\x90\ -\x00\x00\x03\x7a\x00\x01\x00\x00\x00\x01\x00\x06\xe0\xf8\ -\x00\x00\x07\x24\x00\x00\x00\x00\x00\x01\x00\x07\xd7\x23\ -\x00\x00\x05\x7a\x00\x00\x00\x00\x00\x01\x00\x07\x73\x70\ -\x00\x00\x05\x1a\x00\x01\x00\x00\x00\x01\x00\x07\x51\xce\ -\x00\x00\x03\x58\x00\x01\x00\x00\x00\x01\x00\x06\xd7\xff\ -\x00\x00\x06\x00\x00\x01\x00\x00\x00\x01\x00\x07\x90\x93\ -\x00\x00\x06\xfa\x00\x01\x00\x00\x00\x01\x00\x07\xcf\x8e\ -\x00\x00\x04\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x13\x61\ -\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc5\xe9\ +\x00\x00\x06\x96\x00\x01\x00\x00\x00\x01\x00\x07\xac\x45\ +\x00\x00\x05\x76\x00\x00\x00\x00\x00\x01\x00\x07\x63\x49\ +\x00\x00\x04\x12\x00\x00\x00\x00\x00\x01\x00\x07\x05\x4d\ +\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x08\x04\x1a\ +\x00\x00\x06\x68\x00\x01\x00\x00\x00\x01\x00\x07\xa5\x70\ +\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x07\x13\xbc\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x07\x27\x43\ +\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\xea\xab\ +\x00\x00\x07\x60\x00\x00\x00\x00\x00\x01\x00\x07\xe0\xd6\ +\x00\x00\x05\xb6\x00\x00\x00\x00\x00\x01\x00\x07\x7d\x23\ +\x00\x00\x05\x56\x00\x01\x00\x00\x00\x01\x00\x07\x5b\x81\ +\x00\x00\x03\x94\x00\x01\x00\x00\x00\x01\x00\x06\xe1\xb2\ +\x00\x00\x06\x3c\x00\x01\x00\x00\x00\x01\x00\x07\x9a\x46\ \x00\x00\x03\x38\x00\x01\x00\x00\x00\x01\x00\x06\xcf\x91\ -\x00\x00\x05\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x82\xde\ -\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x07\x39\x8b\ -\x00\x00\x05\xd8\x00\x01\x00\x00\x00\x01\x00\x07\x88\x2e\ -\x00\x00\x04\xf8\x00\x01\x00\x00\x00\x01\x00\x07\x4a\x0c\ -\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x07\xaa\xd7\ -\x00\x00\x04\x86\x00\x01\x00\x00\x00\x01\x00\x07\x22\xa7\ -\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x07\xc7\x14\ -\x00\x00\x06\xae\x00\x01\x00\x00\x00\x01\x00\x07\xbc\xda\ -\x00\x00\x05\x5a\x00\x01\x00\x00\x00\x01\x00\x07\x6d\x58\ -\x00\x00\x07\x50\x00\x00\x00\x00\x00\x01\x00\x07\xe8\xf2\ -\x00\x00\x03\xac\x00\x00\x00\x00\x00\x01\x00\x06\xe9\x3a\ -\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x07\x2a\x8f\ +\x00\x00\x07\x36\x00\x01\x00\x00\x00\x01\x00\x07\xd9\x41\ +\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x07\x1d\x14\ +\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc5\xe9\ +\x00\x00\x03\x74\x00\x01\x00\x00\x00\x01\x00\x06\xd9\x44\ +\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x07\x8c\x91\ +\x00\x00\x05\x0a\x00\x00\x00\x00\x00\x01\x00\x07\x43\x3e\ +\x00\x00\x06\x14\x00\x01\x00\x00\x00\x01\x00\x07\x91\xe1\ +\x00\x00\x05\x34\x00\x01\x00\x00\x00\x01\x00\x07\x53\xbf\ +\x00\x00\x06\xc0\x00\x00\x00\x00\x00\x01\x00\x07\xb4\x8a\ +\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x07\x2c\x5a\ +\x00\x00\x07\x0a\x00\x01\x00\x00\x00\x01\x00\x07\xd0\xc7\ +\x00\x00\x06\xea\x00\x01\x00\x00\x00\x01\x00\x07\xc6\x8d\ +\x00\x00\x05\x96\x00\x01\x00\x00\x00\x01\x00\x07\x77\x0b\ +\x00\x00\x07\x8c\x00\x00\x00\x00\x00\x01\x00\x07\xf2\xa5\ +\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x06\xf2\xed\ +\x00\x00\x04\xec\x00\x00\x00\x00\x00\x01\x00\x07\x34\x42\ \x00\x00\x02\xda\x00\x01\x00\x00\x00\x01\x00\x06\xbe\x99\ \x00\x00\x02\xb2\x00\x01\x00\x00\x00\x01\x00\x06\xb6\xfd\ " diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc index 452ecf5b5c..8197a7a2c9 100644 --- a/src/Mod/Arch/Resources/Arch.qrc +++ b/src/Mod/Arch/Resources/Arch.qrc @@ -30,6 +30,7 @@ icons/Arch_Check.svg icons/Arch_SelectNonManifold.svg icons/Arch_MergeWalls.svg + icons/Arch_Wall_Tree_Assembly.svg ui/archprefs-base.ui translations/Arch_af.qm translations/Arch_de.qm diff --git a/src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg b/src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg new file mode 100644 index 0000000000..57db4d808b --- /dev/null +++ b/src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 745de1925efd389b6076b033ca52ae24d61c958f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 18 Apr 2013 13:00:39 -0300 Subject: [PATCH 20/53] Draft: Small fix to Shape2DView --- src/Mod/Draft/Draft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8cf610d06f..986b006b4b 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -3406,7 +3406,7 @@ class _Shape2DView(_DraftObject): def getProjected(self,obj,shape,direction): "returns projected edges from a shape and a direction" - import Part,Drawing + import Part,Drawing,DraftGeomUtils edges = [] groups = Drawing.projectEx(shape,direction) for g in groups[0:5]: From bbed835d6faf9fd8900a34c158d1e57a14392d79 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 18 Apr 2013 13:48:49 -0300 Subject: [PATCH 21/53] Draft: new method for exporting dxf arcs --- src/Mod/Draft/importDXF.py | 39 ++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 35ef8a2b68..7c19cc0a55 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1212,10 +1212,9 @@ def getArcData(edge): # closed circle return DraftVecUtils.tup(ce), radius, 0, 0 else: - # find direction of arc - tang1 = edge.Curve.tangent(edge.ParameterRange[0]) - tang2 = edge.Curve.tangent(edge.ParameterRange[1]) - + # method 1 - find direction of arc from tangents - not reliable + #tang1 = edge.Curve.tangent(edge.ParameterRange[0]) + #tang2 = edge.Curve.tangent(edge.ParameterRange[1]) # following code doesn't seem to give right result? # cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2])) # if cross1[2] > 0: # >0 ccw <0 cw @@ -1225,23 +1224,31 @@ def getArcData(edge): # ve1 = edge.Vertexes[-1].Point # ve2 = edge.Vertexes[0].Point - # check the midpoint seems more reliable + # method 3 - recreate an arc and check if the length is the same ve1 = edge.Vertexes[0].Point ve2 = edge.Vertexes[-1].Point ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce))) ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce))) - ve3 = DraftGeomUtils.findMidpoint(edge) - ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce))) - print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3 - if (ang3 < ang1) and (ang2 < ang3): - print "inverting, case1" - ang1, ang2 = ang2, ang1 - elif (ang3 > ang1) and (ang3 > ang2): - print "inverting, case2" - ang1, ang2 = ang2, ang1 - elif (ang3 < ang1) and (ang3 < ang2): - print "inverting, case3" + + a1 = -DraftVecUtils.angle(ve1.sub(ce)) + a2 = -DraftVecUtils.angle(ve2.sub(ce)) + pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape() + if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()): ang1, ang2 = ang2, ang1 + + # method 2 - check the midpoint - not reliable either + #ve3 = DraftGeomUtils.findMidpoint(edge) + #ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce))) + #print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3 + #if (ang3 < ang1) and (ang2 < ang3): + # print "inverting, case1" + # ang1, ang2 = ang2, ang1 + #elif (ang3 > ang1) and (ang3 > ang2): + # print "inverting, case2" + # ang1, ang2 = ang2, ang1 + #elif (ang3 < ang1) and (ang3 < ang2): + # print "inverting, case3" + # ang1, ang2 = ang2, ang1 return DraftVecUtils.tup(ce), radius, ang1, ang2 def getSplineSegs(edge): From f2eaa0b9f9d972e530a0dee312d2bb75b65b3928 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 19 Apr 2013 18:46:24 -0300 Subject: [PATCH 22/53] 0000979: Move windows with their host wall --- src/Mod/Arch/ArchComponent.py | 8 +++++--- src/Mod/Arch/ArchWall.py | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index e614a2db2e..aa5a300649 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -25,7 +25,7 @@ __title__="FreeCAD Arch Component" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -import FreeCAD,FreeCADGui +import FreeCAD,FreeCADGui,Draft from PyQt4 import QtGui,QtCore from DraftTools import translate @@ -101,7 +101,8 @@ def removeFromComponent(compobject,subobject): l = compobject.Subtractions l.append(subobject) compobject.Subtractions = l - subobject.ViewObject.hide() + if Draft.getType(subobject) != "Window": + subobject.ViewObject.hide() class ComponentTaskPanel: @@ -306,7 +307,8 @@ class Component: if prop in ["Additions","Subtractions"]: if hasattr(obj,prop): for o in getattr(obj,prop): - o.ViewObject.hide() + if Draft.getType(o) != "Window": + o.ViewObject.hide() def processSubShapes(self,obj,base): "Adds additions and subtractions to a base shape" diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index e4a7f4bb72..91d3f26f64 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -335,6 +335,19 @@ class _Wall(ArchComponent.Component): self.hideSubobjects(obj,prop) if prop in ["Base","Height","Width","Align","Additions","Subtractions"]: self.createGeometry(obj) + # propagate movements to children windows + if prop == "Placement": + if obj.Shape: + if not obj.Shape.isNull(): + vo = obj.Shape.Placement.Base + vn = obj.Placement.Base + if not DraftVecUtils.equals(vo,vn): + delta = vn.sub(vo) + for o in obj.OutList: + if (Draft.getType(o) == "Window") or Draft.isClone(o,"Window"): + o.Placement.move(delta) + + def getDefaultValues(self,obj): "returns normal,width,height values from this wall" From bfedeecf9c0a63c47584f84c139db1e389c26946 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 20 Apr 2013 16:51:33 -0300 Subject: [PATCH 23/53] Draft: Added a Draft Ellipse object --- src/Mod/Draft/Draft.py | 55 +++++++++++++++++++++++++++++++------ src/Mod/Draft/DraftTools.py | 2 +- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 986b006b4b..cd9adf39a1 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -808,17 +808,24 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None): select(obj) return obj -def makeEllipse(majradius,minradius,placement=None): - '''makeEllipse(majradius,minradius,[placement]): makes +def makeEllipse(majradius,minradius,placement=None,face=True,support=None): + '''makeEllipse(majradius,minradius,[placement],[face],[support]): makes an ellipse with the given major and minor radius, and optionally a placement.''' - import Part - e = Part.Ellipse(FreeCAD.Vector(0,0,0),majradius,minradius) - newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Ellipse") - newobj.Shape = e.toShape() - if placement: newobj.Placement = placement - FreeCAD.ActiveDocument.recompute() - return newobj + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Ellipse") + _Ellipse(obj) + obj.MajorRadius = majradius + obj.MinorRadius = minradius + obj.Support = support + if placement: + obj.Placement = placement + if gui: + _ViewProviderDraft(obj.ViewObject) + if not face: + obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) + return obj def extrude(obj,vector): '''makeExtrusion(object,vector): extrudes the given object @@ -3033,6 +3040,36 @@ class _Circle(_DraftObject): shape = Part.Face(shape) fp.Shape = shape fp.Placement = plm + +class _Ellipse(_DraftObject): + "The Circle object" + + def __init__(self, obj): + _DraftObject.__init__(self,obj,"Ellipse") + obj.addProperty("App::PropertyDistance","MinorRadius","Base", + "The minor radius of the ellipse") + obj.addProperty("App::PropertyDistance","MajorRadius","Base", + "The major radius of the ellipse") + + def execute(self, fp): + self.createGeometry(fp) + + def onChanged(self, fp, prop): + if prop in ["MinorRadius","MajorRadius"]: + self.createGeometry(fp) + + def createGeometry(self,fp): + import Part + plm = fp.Placement + if fp.MajorRadius < fp.MinorRadius: + msg(translate("Error: Major radius is smaller than the minor radius")) + return + if fp.MajorRadius and fp.MinorRadius: + shape = Part.Ellipse(Vector(0,0,0),fp.MajorRadius,fp.MinorRadius).toShape() + shape = Part.Wire(shape) + shape = Part.Face(shape) + fp.Shape = shape + fp.Placement = plm class _Wire(_DraftObject): "The Wire object" diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 9ff250aa1e..c3070467a6 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1395,7 +1395,7 @@ class Ellipse(Creator): 'pl = FreeCAD.Placement()', 'pl.Rotation.Q='+rot, 'pl.Base = '+DraftVecUtils.toString(center), - 'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl)']) + 'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl,face='+fil+',support='+sup+')']) except: print "Draft: Error: Unable to create object." self.finish(cont=True) From 2d12e32e1b7eb0f2fc828d63ee7b9a72f8da3410 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 21 Apr 2013 14:46:36 -0300 Subject: [PATCH 24/53] Draft: Preliminary DWG support Using the teigha file converter. Warning, only working on linux at the moment. See mantis issue 1103 to help me porting to other OSes --- src/Mod/Draft/InitGui.py | 9 ++++ src/Mod/Draft/importDWG.py | 85 +++++++++++++++++++++++++++++++ src/WindowsInstaller/ModDraft.wxi | 1 + 3 files changed, 95 insertions(+) create mode 100644 src/Mod/Draft/importDWG.py diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index eef95a530e..bca6b05e9a 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -162,3 +162,12 @@ App.addExportType("Autodesk DXF (*.dxf)","importDXF") App.addExportType("Flattened SVG (*.svg)","importSVG") App.addExportType("Open CAD Format (*.oca)","importOCA") +# DWG support +import importDWG +if importDWG.getTeighaConvertor(): + App.addImportType("Autodesk DWG (*.dwg)","importDWG") + App.addExportType("Autodesk DWG (*.dwg)","importDWG") +else: + from DraftTools import translate + FreeCAD.Console.PrintMessage(str(translate("draft","Teigha File Converter not found, DWG support will be disabled.\n"))) + diff --git a/src/Mod/Draft/importDWG.py b/src/Mod/Draft/importDWG.py new file mode 100644 index 0000000000..8a0cf26721 --- /dev/null +++ b/src/Mod/Draft/importDWG.py @@ -0,0 +1,85 @@ +# -*- coding: utf8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2009 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (GPL) * +#* 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 Draft Workbench - DWG importer/exporter" + +if open.__module__ == '__builtin__': + pythonopen = open # to distinguish python built-in open function from the one declared here + +def open(filename): + "called when freecad opens a file." + teigha = getTeighaConvertor() + dxf = convertToDxf(filename) + import importDXF + doc = importDXF.open(dxf) + return doc + +def insert(filename,docname): + "called when freecad imports a file" + dxf = convertToDxf(filemname) + import importDXF + doc = importDXF.insert(dxf,docname) + return doc + +def export(objectslist,filename): + "called when freecad exports a file" + import importDXF,os,tempfile + outdir = tempfile.mkdtemp() + dxf = outdir + os.sep + os.path.splitext(os.path.basename(filename))[0] + ".dxf" + importDXF.export(objectslist,dxf) + convertToDwg(dxf,filename) + return filename + +def getTeighaConvertor(): + "finds the Teigha Convertor executable" + import os,platform + if platform.system() == "Linux": + teigha = "/usr/bin/TeighaFileConverter" + if os.path.exists(teigha): + return teigha + return None + +def convertToDxf(dwgfilename): + "converts a DWG file to DXF" + import os,tempfile + teigha = getTeighaConvertor() + indir = os.path.dirname(dwgfilename) + outdir = tempfile.mkdtemp() + basename = os.path.basename(dwgfilename) + cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DXF" "0" "1" "' + basename + '"' + print "converting " + cmdline + os.system(cmdline) + return outdir + os.sep + os.path.splitext(basename)[0] + ".dxf" + +def convertToDwg(dxffilename,dwgfilename): + "converts a DXF file to DWG" + import os + teigha = getTeighaConvertor() + indir = os.path.dirname(dxffilename) + outdir = os.path.dirname(dwgfilename) + basename = os.path.basename(dxffilename) + cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DWG" "0" "1" "' + basename + '"' + print "converting " + cmdline + os.system(cmdline) + return dwgfilename diff --git a/src/WindowsInstaller/ModDraft.wxi b/src/WindowsInstaller/ModDraft.wxi index 720a39810a..eb43fee409 100644 --- a/src/WindowsInstaller/ModDraft.wxi +++ b/src/WindowsInstaller/ModDraft.wxi @@ -40,6 +40,7 @@ + From 05bbf9c67c3485e015fe13a1c7da3fa2af0ef9d7 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 21 Apr 2013 19:22:30 -0300 Subject: [PATCH 25/53] Draft: fixed Draft's cmake file --- src/Mod/Draft/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 3d12885618..0b0822a831 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -13,6 +13,7 @@ SET(Draft_SRCS importDXF.py importOCA.py importSVG.py + importDWG.py importAirfoilDAT.py macros.py Draft_rc.py From 5dbee5ef8775ac21b2c6ebc872daa66c2ccfa188 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 21 Apr 2013 23:32:34 -0300 Subject: [PATCH 26/53] Draft: dwg support in windows --- src/Mod/Draft/InitGui.py | 2 +- src/Mod/Draft/importDWG.py | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index bca6b05e9a..add28732aa 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -164,7 +164,7 @@ App.addExportType("Open CAD Format (*.oca)","importOCA") # DWG support import importDWG -if importDWG.getTeighaConvertor(): +if importDWG.getTeighaConverter(): App.addImportType("Autodesk DWG (*.dwg)","importDWG") App.addExportType("Autodesk DWG (*.dwg)","importDWG") else: diff --git a/src/Mod/Draft/importDWG.py b/src/Mod/Draft/importDWG.py index 8a0cf26721..bbfc947a08 100644 --- a/src/Mod/Draft/importDWG.py +++ b/src/Mod/Draft/importDWG.py @@ -29,7 +29,6 @@ if open.__module__ == '__builtin__': def open(filename): "called when freecad opens a file." - teigha = getTeighaConvertor() dxf = convertToDxf(filename) import importDXF doc = importDXF.open(dxf) @@ -51,19 +50,29 @@ def export(objectslist,filename): convertToDwg(dxf,filename) return filename -def getTeighaConvertor(): - "finds the Teigha Convertor executable" +def getTeighaConverter(): + "finds the Teigha Converter executable" import os,platform + teigha = None if platform.system() == "Linux": teigha = "/usr/bin/TeighaFileConverter" - if os.path.exists(teigha): - return teigha + elif platform.system() == "Windows": + odadir = "C:\Program Files\ODA" + if os.path.exists(odadir): + subdirs = os.walk(odadir).next()[1] + for sub in subdirs: + t = odadir + os.sep + sub + os.sep + "TeighaFileConverter.exe" + if os.path.exists(t): + teigha = t + if teigha: + if os.path.exists(teigha): + return teigha return None def convertToDxf(dwgfilename): "converts a DWG file to DXF" import os,tempfile - teigha = getTeighaConvertor() + teigha = getTeighaConverter() indir = os.path.dirname(dwgfilename) outdir = tempfile.mkdtemp() basename = os.path.basename(dwgfilename) @@ -75,7 +84,7 @@ def convertToDxf(dwgfilename): def convertToDwg(dxffilename,dwgfilename): "converts a DXF file to DWG" import os - teigha = getTeighaConvertor() + teigha = getTeighaConverter() indir = os.path.dirname(dxffilename) outdir = os.path.dirname(dwgfilename) basename = os.path.basename(dxffilename) From 746b5a31b536a4283ce95f00ea4418ffb02029bb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 24 Apr 2013 12:09:46 -0300 Subject: [PATCH 27/53] 0000981: Arch groups now have a placement --- src/Mod/Arch/ArchFloor.py | 12 +++++++++++- src/Mod/Draft/DraftTools.py | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index f7eb0c75cb..bdbcb8b597 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -78,6 +78,8 @@ class _Floor: def __init__(self,obj): obj.addProperty("App::PropertyLength","Height","Base", str(translate("Arch","The height of this floor"))) + obj.addProperty("App::PropertyPlacement","Placement","Base", + str(translate("Arch","The placement of this group"))) self.Type = "Floor" obj.Proxy = self self.Object = obj @@ -90,10 +92,18 @@ class _Floor: self.Type = state def execute(self,obj): - pass + if hasattr(obj,"Placement"): + self.OldPlacement = obj.Placement.copy() def onChanged(self,obj,prop): self.Object = obj + if prop == "Placement": + if hasattr(self,"OldPlacement"): + delta = obj.Placement.Base.sub(self.OldPlacement.Base) + for o in obj.Group: + if hasattr(o,"Placement"): + o.Placement.move(delta) + self.OldPlacement = FreeCAD.Placement(obj.Placement) def addObject(self,child): if hasattr(self,"Object"): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index c3070467a6..33fb5d6ca1 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1936,7 +1936,14 @@ class Move(Modifier): def proceed(self): if self.call: self.view.removeEventCallback("SoEvent",self.call) self.sel = Draft.getSelection() - self.sel = Draft.getGroupContents(self.sel) + # testing for special case: only Arch groups in selection + onlyarchgroups = True + for o in self.sel: + if not(Draft.getType(o) in ["Floor","Building","Site"]): + onlyarchgroups = False + if not onlyarchgroups: + # arch groups can be moved, no need to add their children + self.sel = Draft.getGroupContents(self.sel) self.ui.pointUi(self.name) self.ui.modUi() self.ui.xValue.setFocus() From ea173ab5c7bdbd8684b2c2d732b3e35a3346b99e Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:01:39 +0200 Subject: [PATCH 28/53] Fix whitespace --- src/Base/Uuid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Base/Uuid.cpp b/src/Base/Uuid.cpp index 2c1f44fa31..1fac7ac949 100644 --- a/src/Base/Uuid.cpp +++ b/src/Base/Uuid.cpp @@ -88,7 +88,7 @@ void Uuid::setValue(const char* sString) void Uuid::setValue(const std::string &sString) { - setValue(sString.c_str()); + setValue(sString.c_str()); } const std::string& Uuid::getValue(void) const From b1b4ada7f445ff7b15869d0909a514baa74ae19e Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:03:39 +0200 Subject: [PATCH 29/53] Fix GNUC compiler settings --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70f3691321..104dffe66e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) include(cMake/ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) add_definitions(-DHAVE_CONFIG_H) - add_definitions(-Wno-write-strings) - add_definitions(-Wno-deprecated) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-write-strings") INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) # get linker errors as soon as possible and not at runtime e.g. for modules if(UNIX) @@ -271,7 +270,6 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X) # -------------------------------- Eigen -------------------------------- - #find_package(Eigen2) find_package(Eigen3) # -------------------------------- ODE ---------------------------------- From 3e02c27d483038b10c1c27e248e2c9c9095c3aa3 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:03:58 +0200 Subject: [PATCH 30/53] Fix typo --- ChangeLog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index ae9473443b..568dcdfa3c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,4 +1,4 @@ -Changelog you finde now here: +Changelog you find now here: https://sourceforge.net/apps/mantisbt/free-cad/changelog_page.php Version: 0.12 From 1be598ac0644aea5512c68558454ca199d32e2b2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:05:40 +0200 Subject: [PATCH 31/53] Allow to save/load XML to/from buffer --- src/Base/Parameter.cpp | 134 +++++++++++++++-------------------------- src/Base/Parameter.h | 8 +-- 2 files changed, 54 insertions(+), 88 deletions(-) diff --git a/src/Base/Parameter.cpp b/src/Base/Parameter.cpp index 52ae32023e..031d697c66 100644 --- a/src/Base/Parameter.cpp +++ b/src/Base/Parameter.cpp @@ -37,6 +37,7 @@ # endif # include # include +# include # include # include # include @@ -1080,7 +1081,23 @@ bool ParameterManager::LoadOrCreateDocument(const char* sFileName) int ParameterManager::LoadDocument(const char* sFileName) { Base::FileInfo file(sFileName); - + + try { +#if defined (FC_OS_WIN32) + LocalFileInputSource inputSource((XMLCh*)file.toStdWString().c_str()); +#else + LocalFileInputSource inputSource(XStr(file.filePath().c_str()).unicodeForm()); +#endif + return LoadDocument(inputSource); + } + catch (...) { + std::cerr << "An error occurred during parsing\n " << std::endl; + return 0; + } +} + +int ParameterManager::LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource& inputSource) +{ // // Create our parser, then attach an error handler to the parser. // The parser will call back to methods of the ErrorHandler if it @@ -1102,11 +1119,7 @@ int ParameterManager::LoadDocument(const char* sFileName) // bool errorsOccured = false; try { -#if defined (FC_OS_WIN32) - parser->parse((XMLCh*)file.toStdWString().c_str()); -#else - parser->parse(file.filePath().c_str()); -#endif + parser->parse(inputSource); } catch (const XMLException& e) { @@ -1152,10 +1165,36 @@ int ParameterManager::LoadDocument(const char* sFileName) } void ParameterManager::SaveDocument(const char* sFileName) const +{ + Base::FileInfo file(sFileName); + + try { + // + // Plug in a format target to receive the resultant + // XML stream from the serializer. + // + // LocalFileFormatTarget prints the resultant XML stream + // to a file once it receives any thing from the serializer. + // +#if defined (FC_OS_WIN32) + XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str()); +#else + XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str()); +#endif + SaveDocument(myFormTarget); + delete myFormTarget; + } + catch (XMLException& e) { + std::cerr << "An error occurred during creation of output transcoder. Msg is:" + << std::endl + << StrX(e.getMessage()) << std::endl; + } +} + +void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const { #if (XERCES_VERSION_MAJOR == 2) DOMPrintFilter *myFilter = 0; - Base::FileInfo file(sFileName); try { // get a serializer, an instance of DOMWriter @@ -1199,31 +1238,17 @@ void ParameterManager::SaveDocument(const char* sFileName) const if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint)) theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint); - // - // Plug in a format target to receive the resultant - // XML stream from the serializer. - // - // LocalFileFormatTarget prints the resultant XML stream - // to a file once it receives any thing from the serializer. - // -#if defined (FC_OS_WIN32) - XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str()); -#else - XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str()); -#endif - // // do the serialization through DOMWriter::writeNode(); // - theSerializer->writeNode(myFormTarget, *_pDocument); + theSerializer->writeNode(pFormatTarget, *_pDocument); delete theSerializer; // - // Filter, formatTarget and error handler + // Filter and error handler // are NOT owned by the serializer. // - delete myFormTarget; delete myErrorHandler; if (gUseFilter) @@ -1236,8 +1261,6 @@ void ParameterManager::SaveDocument(const char* sFileName) const << StrX(e.getMessage()) << std::endl; } #else - Base::FileInfo file(sFileName); - try { // get a serializer, an instance of DOMWriter XMLCh tempStr[100]; @@ -1250,70 +1273,15 @@ void ParameterManager::SaveDocument(const char* sFileName) const DOMConfiguration* config = theSerializer->getDomConfig(); config->setParameter(XStr("format-pretty-print").unicodeForm(),true); - // plug in user's own filter - if (gUseFilter) { - // even we say to show attribute, but the DOMWriter - // will not show attribute nodes to the filter as - // the specs explicitly says that DOMWriter shall - // NOT show attributes to DOMWriterFilter. - // - // so DOMNodeFilter::SHOW_ATTRIBUTE has no effect. - // same DOMNodeFilter::SHOW_DOCUMENT_TYPE, no effect. - // -// myFilter = new DOMPrintFilter(DOMNodeFilter::SHOW_ELEMENT | -// DOMNodeFilter::SHOW_ATTRIBUTE | -// DOMNodeFilter::SHOW_DOCUMENT_TYPE -// ); -// theSerializer->setFilter(myFilter); - } - - // plug in user's own error handler - DOMErrorHandler *myErrorHandler = new DOMPrintErrorHandler(); -// theSerializer->setErrorHandler(myErrorHandler); - - // set feature if the serializer supports the feature/mode -// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections)) -// theSerializer->setFeature(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections); - -// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent)) -// theSerializer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent); - -// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint)) -// theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint); - - // - // Plug in a format target to receive the resultant - // XML stream from the serializer. - // - // LocalFileFormatTarget prints the resultant XML stream - // to a file once it receives any thing from the serializer. - // -#if defined (FC_OS_WIN32) - XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str()); -#else - XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str()); -#endif - // // do the serialization through DOMWriter::writeNode(); // DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput(); theOutput->setEncoding(gOutputEncoding); - theOutput->setByteStream(myFormTarget); + theOutput->setByteStream(pFormatTarget); theSerializer->write(_pDocument, theOutput); delete theSerializer; - - // - // Filter, formatTarget and error handler - // are NOT owned by the serializer. - // - delete myFormTarget; - delete myErrorHandler; - -// if (gUseFilter) -// delete myFilter; - } catch (XMLException& e) { std::cerr << "An error occurred during creation of output transcoder. Msg is:" @@ -1327,6 +1295,7 @@ void ParameterManager::CreateDocument(void) { // creating a document from screatch DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(XStr("Core").unicodeForm()); + delete _pDocument; _pDocument = impl->createDocument( 0, // root element namespace URI. XStr("FCParameters").unicodeForm(), // root element name @@ -1337,11 +1306,8 @@ void ParameterManager::CreateDocument(void) _pGroupNode = _pDocument->createElement(XStr("FCParamGroup").unicodeForm()); ((DOMElement*)_pGroupNode)->setAttribute(XStr("Name").unicodeForm(), XStr("Root").unicodeForm()); rootElem->appendChild(_pGroupNode); - - } - void ParameterManager::CheckDocument() const { diff --git a/src/Base/Parameter.h b/src/Base/Parameter.h index cb50562609..c50e1595a1 100644 --- a/src/Base/Parameter.h +++ b/src/Base/Parameter.h @@ -60,6 +60,8 @@ XERCES_CPP_NAMESPACE_BEGIN class DOMNode; class DOMElement; class DOMDocument; +class XMLFormatTarget; +class InputSource; XERCES_CPP_NAMESPACE_END class ParameterManager; @@ -266,13 +268,11 @@ public: static void Init(void); int LoadDocument(const char* sFileName); - + int LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource&); bool LoadOrCreateDocument(const char* sFileName); - void SaveDocument(const char* sFileName) const; - + void SaveDocument(XERCES_CPP_NAMESPACE_QUALIFIER XMLFormatTarget* pFormatTarget) const; void CreateDocument(void); - void CheckDocument() const; private: From ae4d554021d3e1aba44be3e69ab7ecb2563080a5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:06:18 +0200 Subject: [PATCH 32/53] Allow to save/load XML to/from buffer --- src/Base/PreCompiled.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 69bdb90f71..018dbd6a43 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -82,6 +82,7 @@ #include #include #include +#include #include #include #include From 0035d9fc764fa09cd3f155f1e91b6b34885e077f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:07:18 +0200 Subject: [PATCH 33/53] Add utility functions to convert between string/wstring --- src/Base/Tools.cpp | 20 ++++++++++++++++++++ src/Base/Tools.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/src/Base/Tools.cpp b/src/Base/Tools.cpp index 43f845f0c6..4cbab7b9df 100644 --- a/src/Base/Tools.cpp +++ b/src/Base/Tools.cpp @@ -24,6 +24,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include +# include #endif # include @@ -122,6 +124,24 @@ std::string Base::Tools::getIdentifier(const std::string& name) return CleanName; } +std::wstring Base::Tools::widen(const std::string& str) +{ + std::wostringstream wstm; + const std::ctype& ctfacet = std::use_facet< std::ctype >(wstm.getloc()); + for (size_t i=0; i& ctfacet = std::use_facet< std::ctype >(stm.getloc()); + for (size_t i=0; i&,int d=0); static std::string addNumber(const std::string&, unsigned int, int d=0); static std::string getIdentifier(const std::string&); + static std::wstring widen(const std::string& str); + static std::string narrow(const std::wstring& str); }; } // namespace Base From e8b12bdb4d750d76a351d543d30174f27bdde39b Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:08:05 +0200 Subject: [PATCH 34/53] Fix const correctness --- src/Gui/Application.cpp | 6 +++--- src/Gui/Application.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 666cb5d77f..da74a7e5f2 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -799,19 +799,19 @@ Gui::Document* Application::getDocument(const App::Document* pDoc) const return 0; } -void Application::showViewProvider(App::DocumentObject* obj) +void Application::showViewProvider(const App::DocumentObject* obj) { ViewProvider* vp = getViewProvider(obj); if (vp) vp->show(); } -void Application::hideViewProvider(App::DocumentObject* obj) +void Application::hideViewProvider(const App::DocumentObject* obj) { ViewProvider* vp = getViewProvider(obj); if (vp) vp->hide(); } -Gui::ViewProvider* Application::getViewProvider(App::DocumentObject* obj) const +Gui::ViewProvider* Application::getViewProvider(const App::DocumentObject* obj) const { App::Document* doc = obj->getDocument(); if (doc) { diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 44a73d0c67..1901c36942 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -148,11 +148,11 @@ public: */ Gui::Document* getDocument(const App::Document* pDoc) const; /// Shows the associated view provider of the given object - void showViewProvider(App::DocumentObject*); + void showViewProvider(const App::DocumentObject*); /// Hides the associated view provider of the given object - void hideViewProvider(App::DocumentObject*); + void hideViewProvider(const App::DocumentObject*); /// Get the view provider of the given object - Gui::ViewProvider* getViewProvider(App::DocumentObject*) const; + Gui::ViewProvider* getViewProvider(const App::DocumentObject*) const; //@} /// true when the application shuting down From 81865502dcce738f1e6b6cd4ae95ad1283b3a310 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:09:18 +0200 Subject: [PATCH 35/53] Make Command::getSelection static --- src/Gui/Command.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/Command.h b/src/Gui/Command.h index 255a7dd2f6..7b77d4a4c0 100644 --- a/src/Gui/Command.h +++ b/src/Gui/Command.h @@ -184,7 +184,7 @@ public: /// Get pointer to the Application Window static Application* getGuiApplication(void); /// Get a reference to the selection - Gui::SelectionSingleton& getSelection(void); + static Gui::SelectionSingleton& getSelection(void); /// Get pointer to the active gui document Gui::Document* getActiveGuiDocument(void) const; /** Get pointer to the named or active App document From 11128a4ef8560ce0a37168667553c48d5a86e6eb Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:10:33 +0200 Subject: [PATCH 36/53] Allow to show more parameter sets in parameter editor --- src/Gui/DlgParameterImp.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Gui/DlgParameterImp.cpp b/src/Gui/DlgParameterImp.cpp index 586e2c1b9f..ee2ab82b86 100644 --- a/src/Gui/DlgParameterImp.cpp +++ b/src/Gui/DlgParameterImp.cpp @@ -82,15 +82,18 @@ DlgParameterImp::DlgParameterImp( QWidget* parent, Qt::WFlags fl ) qApp->translate( "Gui::Dialog::DlgParameterImp", "User parameter" ); #endif - const std::map rcList = App::GetApplication().GetParameterSetList(); + ParameterManager* sys = App::GetApplication().GetParameterSet("System parameter"); + const std::map& rcList = App::GetApplication().GetParameterSetList(); for (std::map::const_iterator it= rcList.begin();it!=rcList.end();++it) { - parameterSet->addItem(tr(it->first.c_str()), QVariant(QByteArray(it->first.c_str()))); + if (it->second != sys) // for now ignore system parameters because they are nowhere used + parameterSet->addItem(tr(it->first.c_str()), QVariant(QByteArray(it->first.c_str()))); } QByteArray cStr("User parameter"); parameterSet->setCurrentIndex(parameterSet->findData(cStr)); onChangeParameterSet(parameterSet->currentIndex()); - parameterSet->hide(); + if (parameterSet->count() < 2) + parameterSet->hide(); connect(parameterSet, SIGNAL(activated(int)), this, SLOT(onChangeParameterSet(int))); @@ -238,6 +241,13 @@ void DlgParameterImp::onChangeParameterSet(int index) if (!rcParMngr) return; + if (rcParMngr == App::GetApplication().GetParameterSet("System parameter")) + buttonSaveToDisk->setEnabled(true); + else if (rcParMngr == App::GetApplication().GetParameterSet("User parameter")) + buttonSaveToDisk->setEnabled(true); + else + buttonSaveToDisk->setEnabled(false); + // remove all labels paramGroup->clear(); paramValue->clear(); @@ -282,18 +292,19 @@ void DlgParameterImp::onChangeParameterSet(int index) if (parent) paramGroup->setCurrentItem(parent); + else if (paramGroup->topLevelItemCount() > 0) + paramGroup->setCurrentItem(paramGroup->topLevelItem(0)); } void DlgParameterImp::on_buttonSaveToDisk_clicked() { - ParameterManager* sys = App::GetApplication().GetParameterSet("System parameter"); - if (sys) { - sys->SaveDocument(App::Application::Config()["SystemParameter"].c_str()); - } - ParameterManager* user = App::GetApplication().GetParameterSet("User parameter"); - if (user) { - user->SaveDocument(App::Application::Config()["UserParameter"].c_str()); - } + int index = parameterSet->currentIndex(); + ParameterManager* parmgr = App::GetApplication().GetParameterSet(parameterSet->itemData(index).toByteArray()); + if (!parmgr) return; + if (parmgr == App::GetApplication().GetParameterSet("System parameter")) + parmgr->SaveDocument(App::Application::Config()["SystemParameter"].c_str()); + else if (parmgr == App::GetApplication().GetParameterSet("User parameter")) + parmgr->SaveDocument(App::Application::Config()["UserParameter"].c_str()); } namespace Gui { From db1edf07021f62276a323846573ab92e03474dc4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:13:20 +0200 Subject: [PATCH 37/53] Implement a more user-friendly selection tool --- src/Gui/MouseSelection.cpp | 187 +++++++++++++++++++++++++++++++ src/Gui/MouseSelection.h | 40 +++++++ src/Gui/View3DInventorViewer.cpp | 61 ++++++++++ src/Gui/View3DInventorViewer.h | 3 + 4 files changed, 291 insertions(+) diff --git a/src/Gui/MouseSelection.cpp b/src/Gui/MouseSelection.cpp index a4733b5451..e5b92b0796 100644 --- a/src/Gui/MouseSelection.cpp +++ b/src/Gui/MouseSelection.cpp @@ -458,6 +458,193 @@ int PolyClipSelection::popupMenu() // ----------------------------------------------------------------------------------- +BrushSelection::BrushSelection() + : r(1.0f), g(0.0f), b(0.0f), a(0.0f), l(2.0f) +{ + m_iNodes = 0; + m_bWorking = false; +} + +void BrushSelection::initialize() +{ + QPixmap p(cursor_cut_scissors); + QCursor cursor(p, 4, 4); + _pcView3D->getWidget()->setCursor(cursor); +} + +void BrushSelection::terminate() +{ +} + +void BrushSelection::setColor(float r, float g, float b, float a) +{ + this->r = r; + this->g = g; + this->b = b; + this->a = a; +} + +void BrushSelection::setLineWidth(float l) +{ + this->l = l; +} + +void BrushSelection::draw () +{ + if (mustRedraw){ + if (_cNodeVector.size() > 1) { + QPoint start = _cNodeVector.front(); + for (std::vector::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) { + _pcView3D->drawLine(start.x(),start.y(),it->x(), it->y(), + this->l, this->r, this->g, this->b, this->a); + start = *it; + } + } + + // recursive call, but no infinite loop + mustRedraw = false; + draw(); + } + if (m_bWorking) { + _pcView3D->drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold, + this->l, this->r, this->g, this->b, this->a); + } +} + +BrushSelection::~BrushSelection() +{ +} + +int BrushSelection::popupMenu() +{ + QMenu menu; + QAction* fi = menu.addAction(QObject::tr("Finish")); + menu.addAction(QObject::tr("Clear")); + QAction* ca = menu.addAction(QObject::tr("Cancel")); + if (getPositions().size() < 3) + fi->setEnabled(false); + QAction* id = menu.exec(QCursor::pos()); + if (id == fi) + return Finish; + else if (id == ca) + return Cancel; + else + return Restart; +} + +int BrushSelection::mouseButtonEvent(const SoMouseButtonEvent * const e, const QPoint& pos) +{ + const int button = e->getButton(); + const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE; + + if (press) { + switch (button) + { + case SoMouseButtonEvent::BUTTON1: + { + // start working from now on + if (!m_bWorking) { + m_bWorking = true; + // clear the old polygon + _cNodeVector.clear(); + _pcView3D->getGLWidget()->update(); + + _cNodeVector.push_back(pos); + + m_iXnew = pos.x(); m_iYnew = pos.y(); + m_iXold = pos.x(); m_iYold = pos.y(); + } + } break; + case SoMouseButtonEvent::BUTTON2: + { + if (_cNodeVector.size() > 0) { + if (_cNodeVector.back() != pos) + _cNodeVector.push_back(pos); + m_iXnew = pos.x(); m_iYnew = pos.y(); + m_iXold = pos.x(); m_iYold = pos.y(); + } + } break; + default: + { + } break; + } + } + // release + else { + switch (button) + { + case SoMouseButtonEvent::BUTTON1: + return Finish; + case SoMouseButtonEvent::BUTTON2: + { + QCursor cur = _pcView3D->getWidget()->cursor(); + _pcView3D->getWidget()->setCursor(m_cPrevCursor); + + // The pop-up menu should be shown when releasing mouse button because + // otherwise the navigation style doesn't get the UP event and gets into + // an inconsistent state. + int id = popupMenu(); + if (id == Finish || id == Cancel) { + releaseMouseModel(); + } + else if (id == Restart) { + m_bWorking = false; + m_iNodes = 0; + _pcView3D->getWidget()->setCursor(cur); + } + return id; + } break; + default: + { + } break; + } + } + + return Continue; +} + +int BrushSelection::locationEvent(const SoLocation2Event * const e, const QPoint& pos) +{ + // do all the drawing stuff for us + QPoint clPoint = pos; + + if (m_bWorking) { + // check the position + QRect r = _pcView3D->getGLWidget()->rect(); + if (!r.contains(clPoint)) { + if (clPoint.x() < r.left()) + clPoint.setX( r.left()); + if (clPoint.x() > r.right()) + clPoint.setX(r.right()); + if (clPoint.y() < r.top()) + clPoint.setY(r.top()); + if (clPoint.y() > r.bottom()) + clPoint.setY(r.bottom()); + } + + SbVec2s last = _clPoly.back(); + SbVec2s curr = e->getPosition(); + if (abs(last[0]-curr[0]) > 20 || abs(last[1]-curr[1]) > 20) + _clPoly.push_back(curr); + _cNodeVector.push_back(clPoint); + } + + m_iXnew = clPoint.x(); + m_iYnew = clPoint.y(); + draw(); + m_iXold = clPoint.x(); + m_iYold = clPoint.y(); + + return Continue; +} + +int BrushSelection::keyboardEvent( const SoKeyboardEvent * const e ) +{ + return Continue; +} + +// ----------------------------------------------------------------------------------- + RectangleSelection::RectangleSelection() { m_bWorking = false; diff --git a/src/Gui/MouseSelection.h b/src/Gui/MouseSelection.h index fd8716e728..b26cdea30b 100644 --- a/src/Gui/MouseSelection.h +++ b/src/Gui/MouseSelection.h @@ -27,6 +27,7 @@ #include #include #include +#include // forwards class QMouseEvent; @@ -156,6 +157,45 @@ protected: // ----------------------------------------------------------------------------------- +/** + * The brush selection class + * \author Werner Mayer + */ +class GuiExport BrushSelection : public BaseMouseSelection +{ +public: + BrushSelection(); + virtual ~BrushSelection(); + + /// set the new mouse cursor + virtual void initialize(); + /// do nothing + virtual void terminate(); + + // Settings + void setColor(float r, float g, float b, float a=0); + void setLineWidth(float); + +protected: + virtual int mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos ); + virtual int locationEvent ( const SoLocation2Event * const e, const QPoint& pos ); + virtual int keyboardEvent ( const SoKeyboardEvent * const e ); + + /// draw the polygon + virtual void draw (); + virtual int popupMenu(); + +protected: + std::vector _cNodeVector; + int m_iNodes; + bool m_bWorking; + +private: + float r,g,b,a,l; +}; + +// ----------------------------------------------------------------------------------- + /** * The selection mouse model class * Draws a rectangle for selection diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 5e1963687e..5843f4bea3 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1620,6 +1620,67 @@ void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2) this->glUnlockNormal(); } +void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2, GLfloat line, + GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha, + GLenum op) +{ + // Make current context + SbVec2s view = this->getGLSize(); + this->glLockNormal(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, view[0], 0, view[1], -1, 1); + + // Store GL state + glPushAttrib(GL_ALL_ATTRIB_BITS); + GLfloat depthrange[2]; + glGetFloatv(GL_DEPTH_RANGE, depthrange); + GLdouble projectionmatrix[16]; + glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); + + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); + glDepthRange(0,0); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_BLEND); + + glLineWidth(line); + glColor4f(red, green, blue, alpha); + glViewport(0, 0, view[0], view[1]); + + if (op > 0) { + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(op); + } + glDrawBuffer(GL_FRONT); + + glBegin(GL_LINES); + glVertex3i(x1, view[1]-y1, 0); + glVertex3i(x2, view[1]-y2, 0); + glEnd(); + + glFlush(); + if (op) { + glLogicOp(GL_COPY); + glDisable(GL_COLOR_LOGIC_OP); + } + + // Reset original state + glDepthRange(depthrange[0], depthrange[1]); + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(projectionmatrix); + + glPopAttrib(); + glPopMatrix(); + + // Release the context + this->glUnlockNormal(); +} + /*! Decide if it should be possible to start a spin animation of the model in the viewer by releasing the mouse button while dragging. diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 47cb11de90..88985f8462 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -256,6 +256,9 @@ public: //@{ void drawRect (int x, int y, int w, int h); void drawLine (int x1, int y1, int x2, int y2); + void drawLine (int x1, int y1, int x2, int y2, + GLfloat line, GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha, GLenum op=0); //@} void setGradientBackgroud(bool b); From bbe4aa54cc1e3fdd2a0a5b195893b25802fcd24f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:16:01 +0200 Subject: [PATCH 38/53] Minor changes --- src/Gui/MDIView.h | 7 ++++--- src/Gui/SelectionObjectPyImp.cpp | 2 +- src/Gui/SoAxisCrossKit.h | 1 + src/Gui/View3DInventor.cpp | 5 +---- src/Gui/View3DInventor.h | 2 +- src/Mod/Image/App/ImageBase.cpp | 14 +++++++------- src/Mod/Image/App/ImageBase.h | 2 +- src/Mod/Image/Gui/GLImageBox.cpp | 12 ++++++++++-- src/Mod/Image/Gui/GLImageBox.h | 1 + src/Mod/Image/Gui/Workbench.cpp | 1 - 10 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/Gui/MDIView.h b/src/Gui/MDIView.h index 3a787b5fa5..eb086c53bd 100644 --- a/src/Gui/MDIView.h +++ b/src/Gui/MDIView.h @@ -77,10 +77,7 @@ public: /** @name Printing */ //@{ public Q_SLOTS: - virtual void setOverrideCursor(const QCursor&); - virtual void restoreOverrideCursor(); virtual void print(QPrinter* printer); - public: /** Print content of view */ virtual void print(); @@ -107,6 +104,10 @@ public: virtual void setCurrentViewMode(ViewMode mode); ViewMode currentViewMode() const { return currentMode; } +public Q_SLOTS: + virtual void setOverrideCursor(const QCursor&); + virtual void restoreOverrideCursor(); + Q_SIGNALS: void message(const QString&, int); diff --git a/src/Gui/SelectionObjectPyImp.cpp b/src/Gui/SelectionObjectPyImp.cpp index 5cd52a9f30..34200b2416 100644 --- a/src/Gui/SelectionObjectPyImp.cpp +++ b/src/Gui/SelectionObjectPyImp.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net) * + * Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net) * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Gui/SoAxisCrossKit.h b/src/Gui/SoAxisCrossKit.h index 488c51ee82..644cd64525 100644 --- a/src/Gui/SoAxisCrossKit.h +++ b/src/Gui/SoAxisCrossKit.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 1b2b934ca7..e1a44f3d79 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -772,12 +772,9 @@ bool View3DInventor::hasClippingPlane() const return _viewer->hasClippingPlane(); } -void View3DInventor::setOverlayWidget(GLOverlayWidget* widget) +void View3DInventor::setOverlayWidget(QWidget* widget) { removeOverlayWidget(); - QGLWidget* w = static_cast(_viewer->getGLWidget()); - QImage img = w->grabFrameBuffer(); - widget->setImage(img); stack->addWidget(widget); stack->setCurrentIndex(1); } diff --git a/src/Gui/View3DInventor.h b/src/Gui/View3DInventor.h index e6aba94f2c..de3bc9249b 100644 --- a/src/Gui/View3DInventor.h +++ b/src/Gui/View3DInventor.h @@ -100,7 +100,7 @@ public: void toggleClippingPlane(); bool hasClippingPlane() const; - void setOverlayWidget(GLOverlayWidget*); + void setOverlayWidget(QWidget*); void removeOverlayWidget(); View3DInventorViewer *getViewer(void) const {return _viewer;} diff --git a/src/Mod/Image/App/ImageBase.cpp b/src/Mod/Image/App/ImageBase.cpp index fa078faf91..d3177a1800 100644 --- a/src/Mod/Image/App/ImageBase.cpp +++ b/src/Mod/Image/App/ImageBase.cpp @@ -123,7 +123,7 @@ void ImageBase::clear() _setColorFormat(IB_CF_GREY8, 8); } -// Sets the color format and the dependant parameters +// Sets the color format and the dependent parameters // Returns 0 for OK, -1 for invalid color format int ImageBase::_setColorFormat(int format, unsigned short numSigBitsPerSample) { @@ -235,7 +235,7 @@ int ImageBase::createCopy(void* pSrcPixelData, unsigned long width, unsigned lon // Clear any existing data clear(); - // Set the color format and the dependant parameters + // Set the color format and the dependent parameters if (_setColorFormat(format, numSigBitsPerSample) != 0) return -1; @@ -273,7 +273,7 @@ int ImageBase::pointTo(void* pSrcPixelData, unsigned long width, unsigned long h // Clear any existing data clear(); - // Set the color format and the dependant parameters + // Set the color format and the dependent parameters if (_setColorFormat(format, numSigBitsPerSample) != 0) return -1; @@ -324,15 +324,15 @@ int ImageBase::getSample(int x, int y, unsigned short sampleIndex, double &value case IB_CF_RGBA64: case IB_CF_BGRA64: { - unsigned short* pPix16 = (unsigned short *)_pPixelData; - unsigned short* pSample = pPix16 + _numSamples * (y * _width + x) + sampleIndex; + uint16_t* pPix16 = (uint16_t *)_pPixelData; + uint16_t* pSample = pPix16 + _numSamples * (y * _width + x) + sampleIndex; value = (double)(*pSample); } break; case IB_CF_GREY32: { - unsigned long* pPix32 = (unsigned long *)_pPixelData; - unsigned long* pSample = pPix32 + y * _width + x; + uint32_t* pPix32 = (uint32_t *)_pPixelData; + uint32_t* pSample = pPix32 + y * _width + x; value = (double)(*pSample); } break; diff --git a/src/Mod/Image/App/ImageBase.h b/src/Mod/Image/App/ImageBase.h index 44b061c11f..144699c717 100644 --- a/src/Mod/Image/App/ImageBase.h +++ b/src/Mod/Image/App/ImageBase.h @@ -71,7 +71,7 @@ protected: int _format; // colour format of the pixel data unsigned short _numSigBitsPerSample;// number of significant bits per sample (always <= _numBitsPerSample) - // Dependant parameters + // Dependent parameters unsigned short _numSamples; // number of samples per pixel (e.g. 1 for grey, 3 for rgb, 4 for rgba) unsigned short _numBitsPerSample; // number of bits per sample (e.g. 8 for Grey8) unsigned short _numBytesPerPixel; // number of bytes per pixel (e.g. 1 for Grey8) diff --git a/src/Mod/Image/Gui/GLImageBox.cpp b/src/Mod/Image/Gui/GLImageBox.cpp index bfb54eec08..e29c400cf9 100644 --- a/src/Mod/Image/Gui/GLImageBox.cpp +++ b/src/Mod/Image/Gui/GLImageBox.cpp @@ -45,6 +45,8 @@ using namespace ImageGui; #pragma warning(disable:4305) // init: truncation from const double to float #endif +bool GLImageBox::haveMesa = false; + /* TRANSLATOR ImageGui::GLImageBox */ // Constructor @@ -81,7 +83,13 @@ GLImageBox::~GLImageBox() // Set up the OpenGL rendering state void GLImageBox::initializeGL() { - qglClearColor( Qt::black ); // Let OpenGL clear to black + qglClearColor( Qt::black ); // Let OpenGL clear to black + static bool init = false; + if (!init) { + init = true; + std::string ver = (const char*)(glGetString(GL_VERSION)); + haveMesa = (ver.find("Mesa") != std::string::npos); + } } @@ -170,7 +178,7 @@ void GLImageBox::drawImage() // Load the color map if present if (_pColorMap != 0) { - glPixelTransferf(GL_MAP_COLOR, 1.0); + if (!haveMesa) glPixelTransferf(GL_MAP_COLOR, 1.0); glPixelMapfv(GL_PIXEL_MAP_R_TO_R, _numMapEntries, _pColorMap); glPixelMapfv(GL_PIXEL_MAP_G_TO_G, _numMapEntries, _pColorMap + _numMapEntries); glPixelMapfv(GL_PIXEL_MAP_B_TO_B, _numMapEntries, _pColorMap + _numMapEntries * 2); diff --git a/src/Mod/Image/Gui/GLImageBox.h b/src/Mod/Image/Gui/GLImageBox.h index 91b6ca9dc5..0aeb5121bf 100644 --- a/src/Mod/Image/Gui/GLImageBox.h +++ b/src/Mod/Image/Gui/GLImageBox.h @@ -105,6 +105,7 @@ private: float* _pColorMap; // a RGBA color map (to alter the intensity or colors) int _numMapEntries; // number of entries in color map + static bool haveMesa; }; diff --git a/src/Mod/Image/Gui/Workbench.cpp b/src/Mod/Image/Gui/Workbench.cpp index c07043da93..ed972cecd2 100644 --- a/src/Mod/Image/Gui/Workbench.cpp +++ b/src/Mod/Image/Gui/Workbench.cpp @@ -58,7 +58,6 @@ Gui::ToolBarItem* Workbench::setupToolBars() const Gui::ToolBarItem* Workbench::setupCommandBars() const { - // Part tools Gui::ToolBarItem* root = new Gui::ToolBarItem; Gui::ToolBarItem* img = new Gui::ToolBarItem(root); img->setCommand("Image"); From f03fed87a9f2a19709857afe5dd5cbeaefbc7f37 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:16:56 +0200 Subject: [PATCH 39/53] Implement a TaskGroup class to show widgets without extra header --- src/Gui/TaskView/TaskView.cpp | 84 +++++++++++++++++++++++++++-------- src/Gui/TaskView/TaskView.h | 12 +++++ 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/src/Gui/TaskView/TaskView.cpp b/src/Gui/TaskView/TaskView.cpp index d5f6478091..aa52c86e7e 100644 --- a/src/Gui/TaskView/TaskView.cpp +++ b/src/Gui/TaskView/TaskView.cpp @@ -61,7 +61,72 @@ TaskWidget::~TaskWidget() { } +//************************************************************************** +//************************************************************************** +// TaskGroup +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +TaskGroup::TaskGroup(QWidget *parent) + : iisTaskGroup(parent, false) +{ + setScheme(iisFreeCADTaskPanelScheme::defaultScheme()); +} + +TaskGroup::~TaskGroup() +{ +} + +namespace Gui { namespace TaskView { +class TaskIconLabel : public iisIconLabel { +public: + TaskIconLabel(const QIcon &icon, + const QString &title, + QWidget *parent = 0) + : iisIconLabel(icon, title, parent) { + // do not allow to get the focus because when hiding the task box + // it could cause to activate another MDI view. + setFocusPolicy(Qt::NoFocus); + } + void setTitle(const QString &text) { + myText = text; + update(); + } +}; +} +} + +void TaskGroup::actionEvent (QActionEvent* e) +{ + QAction *action = e->action(); + switch (e->type()) { + case QEvent::ActionAdded: + { + TaskIconLabel *label = new TaskIconLabel( + action->icon(), action->text(), this); + this->addIconLabel(label); + connect(label,SIGNAL(clicked()),action,SIGNAL(triggered())); + break; + } + case QEvent::ActionChanged: + { + // update label when action changes + QBoxLayout* bl = this->groupLayout(); + int index = this->actions().indexOf(action); + if (index < 0) break; + QWidgetItem* item = static_cast(bl->itemAt(index)); + TaskIconLabel* label = static_cast(item->widget()); + label->setTitle(action->text()); + break; + } + case QEvent::ActionRemoved: + { + // cannot change anything + break; + } + default: + break; + } +} //************************************************************************** //************************************************************************** @@ -125,25 +190,6 @@ void TaskBox::hideGroupBox() setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); } -namespace Gui { namespace TaskView { -class TaskIconLabel : public iisIconLabel { -public: - TaskIconLabel(const QIcon &icon, - const QString &title, - QWidget *parent = 0) - : iisIconLabel(icon, title, parent) { - // do not allow to get the focus because when hiding the task box - // it could cause to activate another MDI view. - setFocusPolicy(Qt::NoFocus); - } - void setTitle(const QString &text) { - myText = text; - update(); - } -}; -} -} - void TaskBox::actionEvent (QActionEvent* e) { QAction *action = e->action(); diff --git a/src/Gui/TaskView/TaskView.h b/src/Gui/TaskView/TaskView.h index 9b388d5a2f..72b8100f72 100644 --- a/src/Gui/TaskView/TaskView.h +++ b/src/Gui/TaskView/TaskView.h @@ -57,6 +57,18 @@ public: //~TaskContent(); }; +class GuiExport TaskGroup : public iisTaskGroup, public TaskContent +{ + Q_OBJECT + +public: + TaskGroup(QWidget *parent = 0); + ~TaskGroup(); + +protected: + void actionEvent (QActionEvent*); +}; + /// Father class of content with header and Icon class GuiExport TaskBox : public iisTaskBox, public TaskContent { From a2b4b04c13089505fb46292ec72c2f243dcdcac7 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:18:25 +0200 Subject: [PATCH 40/53] Better exception handling when writing STEP/IGES/BREP files via Python --- src/Mod/Part/App/AppPartPy.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 6d5640d875..edd96dfaf3 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -274,10 +274,11 @@ static PyObject * exporter(PyObject *self, PyObject *args) } } } - } PY_CATCH; - TopoShape shape(comp); - shape.write(filename); + TopoShape shape(comp); + shape.write(filename); + + } PY_CATCH; Py_Return; } From c424b73ee5276b595125d83c2bde7ba7de40db4d Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:19:23 +0200 Subject: [PATCH 41/53] Fix whitespaces --- src/Mod/Mesh/App/Core/Approximation.cpp | 10 +++++----- src/Mod/Mesh/App/Core/MeshIO.cpp | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index 0cc23d4046..2c1731e26c 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -452,8 +452,8 @@ void QuadraticFit::CalcEigenValues(double &dLambda1, double &dLambda2, double &d */ Wm4::Matrix3 akMat(_fCoeff[4], _fCoeff[7]/2.0f, _fCoeff[8]/2.0f, - _fCoeff[7]/2.0f, _fCoeff[5], _fCoeff[9]/2.0f, - _fCoeff[8]/2.0f, _fCoeff[9]/2.0f, _fCoeff[6] ); + _fCoeff[7]/2.0f, _fCoeff[5], _fCoeff[9]/2.0f, + _fCoeff[8]/2.0f, _fCoeff[9]/2.0f, _fCoeff[6] ); Wm4::Matrix3 rkRot, rkDiag; akMat.EigenDecomposition( rkRot, rkDiag ); @@ -476,9 +476,9 @@ void QuadraticFit::CalcZValues( double x, double y, double &dZ1, double &dZ2 ) c assert( _bIsFitted ); double dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+ - _fCoeff[8]*_fCoeff[8]*x*x+2*_fCoeff[8]*x*_fCoeff[9]*y+_fCoeff[9]*_fCoeff[9]*y*y- - 4*_fCoeff[6]*_fCoeff[0]-4*_fCoeff[6]*_fCoeff[1]*x-4*_fCoeff[6]*_fCoeff[2]*y- - 4*_fCoeff[6]*_fCoeff[7]*x*y-4*_fCoeff[6]*_fCoeff[4]*x*x-4*_fCoeff[6]*_fCoeff[5]*y*y; + _fCoeff[8]*_fCoeff[8]*x*x+2*_fCoeff[8]*x*_fCoeff[9]*y+_fCoeff[9]*_fCoeff[9]*y*y- + 4*_fCoeff[6]*_fCoeff[0]-4*_fCoeff[6]*_fCoeff[1]*x-4*_fCoeff[6]*_fCoeff[2]*y- + 4*_fCoeff[6]*_fCoeff[7]*x*y-4*_fCoeff[6]*_fCoeff[4]*x*x-4*_fCoeff[6]*_fCoeff[5]*y*y; if (fabs( _fCoeff[6] ) < 0.000005) { dZ1 = FLOAT_MAX; diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 909c664f54..684df06d61 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -795,17 +795,17 @@ bool MeshInput::LoadPLY (std::istream &inp) } } else { - for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { - if (boost::regex_match(line.c_str(), what, rx_p)) { - pt.x = (float)std::atof(what[1].first); - pt.y = (float)std::atof(what[4].first); - pt.z = (float)std::atof(what[7].first); - meshPoints.push_back(pt); + for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { + if (boost::regex_match(line.c_str(), what, rx_p)) { + pt.x = (float)std::atof(what[1].first); + pt.y = (float)std::atof(what[4].first); + pt.z = (float)std::atof(what[7].first); + meshPoints.push_back(pt); + } + else { + return false; + } } - else { - return false; - } - } } int f1, f2, f3; for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) { From 8218489a0f246bb2859f6a86835a3ce867c9e4fd Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:20:24 +0200 Subject: [PATCH 42/53] Add convenience methods to query selection of a mesh --- src/Mod/Mesh/App/Mesh.cpp | 17 +++++++++++++++++ src/Mod/Mesh/App/Mesh.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 9a13a27a84..fb5084b648 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -587,6 +587,23 @@ void MeshObject::getPointsFromSelection(std::vector& inds) const MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(inds, MeshCore::MeshPoint::SELECTED); } +bool MeshObject::hasSelectedFacets() const +{ + unsigned long ct = MeshCore::MeshAlgorithm(this->_kernel).CountFacetFlag(MeshCore::MeshFacet::SELECTED); + return ct > 0; +} + +bool MeshObject::hasSelectedPoints() const +{ + unsigned long ct = MeshCore::MeshAlgorithm(this->_kernel).CountPointFlag(MeshCore::MeshPoint::SELECTED); + return ct > 0; +} + +std::vector MeshObject::getPointsFromFacets(const std::vector& facets) const +{ + return _kernel.GetFacetPoints(facets); +} + void MeshObject::updateMesh(const std::vector& facets) { std::vector points; diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 441db4de38..a88a06ec37 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -124,6 +124,7 @@ public: double getVolume() const; void getFaces(std::vector &Points,std::vector &Topo, float Accuracy, uint16_t flags=0) const; + std::vector getPointsFromFacets(const std::vector& facets) const; //@} void setKernel(const MeshCore::MeshKernel& m); @@ -211,6 +212,8 @@ public: void addPointsToSelection(const std::vector&) const; void removeFacetsFromSelection(const std::vector&) const; void removePointsFromSelection(const std::vector&) const; + bool hasSelectedFacets() const; + bool hasSelectedPoints() const; void getFacetsFromSelection(std::vector&) const; void getPointsFromSelection(std::vector&) const; void clearFacetSelection() const; From cc4bc130257958f2790b21ce990cd1cb15289caf Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:21:36 +0200 Subject: [PATCH 43/53] Improve methods to select meshes, allow to smooth only selected area of a mesh --- src/Mod/Mesh/Gui/AppMeshGui.cpp | 2 + src/Mod/Mesh/Gui/CMakeLists.txt | 9 + src/Mod/Mesh/Gui/Command.cpp | 26 +- src/Mod/Mesh/Gui/DlgSmoothing.cpp | 138 ++++++- src/Mod/Mesh/Gui/DlgSmoothing.h | 62 +++- src/Mod/Mesh/Gui/DlgSmoothing.ui | 230 +++++------- src/Mod/Mesh/Gui/MeshEditor.cpp | 343 ++++++++++++++++- src/Mod/Mesh/Gui/MeshEditor.h | 72 +++- src/Mod/Mesh/Gui/MeshSelection.cpp | 467 +++++++++++++++++++++++ src/Mod/Mesh/Gui/MeshSelection.h | 89 +++++ src/Mod/Mesh/Gui/RemoveComponents.cpp | 516 ++++++++++---------------- src/Mod/Mesh/Gui/RemoveComponents.h | 59 ++- src/Mod/Mesh/Gui/RemoveComponents.ui | 7 +- src/Mod/Mesh/Gui/Selection.cpp | 108 ++++++ src/Mod/Mesh/Gui/Selection.h | 62 ++++ src/Mod/Mesh/Gui/Selection.ui | 71 ++++ src/Mod/Mesh/Gui/SoPolygon.cpp | 175 +++++++++ src/Mod/Mesh/Gui/SoPolygon.h | 65 ++++ src/Mod/Mesh/Gui/ViewProvider.cpp | 30 +- 19 files changed, 2050 insertions(+), 481 deletions(-) create mode 100644 src/Mod/Mesh/Gui/MeshSelection.cpp create mode 100644 src/Mod/Mesh/Gui/MeshSelection.h create mode 100644 src/Mod/Mesh/Gui/Selection.cpp create mode 100644 src/Mod/Mesh/Gui/Selection.h create mode 100644 src/Mod/Mesh/Gui/Selection.ui create mode 100644 src/Mod/Mesh/Gui/SoPolygon.cpp create mode 100644 src/Mod/Mesh/Gui/SoPolygon.h diff --git a/src/Mod/Mesh/Gui/AppMeshGui.cpp b/src/Mod/Mesh/Gui/AppMeshGui.cpp index a3ff09cc67..624d569727 100644 --- a/src/Mod/Mesh/Gui/AppMeshGui.cpp +++ b/src/Mod/Mesh/Gui/AppMeshGui.cpp @@ -41,6 +41,7 @@ #include "DlgSettingsMeshView.h" #include "SoFCMeshObject.h" #include "SoFCIndexedFaceSet.h" +#include "SoPolygon.h" #include "ViewProvider.h" #include "ViewProviderMeshFaceSet.h" #include "ViewProviderCurvature.h" @@ -111,6 +112,7 @@ void MeshGuiExport initMeshGui() MeshGui::SoFCIndexedFaceSet ::initClass(); MeshGui::SoFCMeshPickNode ::initClass(); MeshGui::SoFCMeshGridNode ::initClass(); + MeshGui::SoPolygon ::initClass(); MeshGui::PropertyMeshKernelItem ::init(); MeshGui::ViewProviderMesh ::init(); MeshGui::ViewProviderMeshObject ::init(); diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index ae4701a0f9..cafca6c7c3 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -24,6 +24,7 @@ set(Mesh_MOC_HDRS MeshEditor.h PropertyEditorMesh.h RemoveComponents.h + Selection.h ) fc_wrap_cpp(Mesh_MOC_SRCS ${Mesh_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${Mesh_MOC_SRCS}) @@ -35,6 +36,7 @@ set(Dialogs_UIC_SRCS DlgSmoothing.ui RemoveComponents.ui Segmentation.ui + Selection.ui ) qt4_wrap_ui(Dialogs_UIC_HDRS ${Dialogs_UIC_SRCS}) SET(Dialogs_SRCS @@ -57,6 +59,9 @@ SET(Dialogs_SRCS Segmentation.ui Segmentation.cpp Segmentation.h + Selection.ui + Selection.cpp + Selection.h ) SOURCE_GROUP("Dialogs" FILES ${Dialogs_SRCS}) @@ -65,6 +70,8 @@ SET(Inventor_SRCS SoFCIndexedFaceSet.h SoFCMeshObject.cpp SoFCMeshObject.h + SoPolygon.cpp + SoPolygon.h ) SOURCE_GROUP("Inventor" FILES ${Inventor_SRCS}) @@ -105,6 +112,8 @@ SET(MeshGui_SRCS PreCompiled.h MeshEditor.cpp MeshEditor.h + MeshSelection.cpp + MeshSelection.h PropertyEditorMesh.cpp PropertyEditorMesh.h Workbench.cpp diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 1bc39d291a..2e71e4ed90 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -1019,9 +1019,19 @@ bool CmdMeshRemoveComponents::isActive(void) { // Check for the selected mesh feature (all Mesh types) App::Document* doc = getDocument(); - return (doc && doc->countObjectsOfType - (Mesh::Feature::getClassTypeId()) > 0 - && !Gui::Control().activeDialog()); + if (!(doc && doc->countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0)) + return false; + Gui::Document* viewDoc = Gui::Application::Instance->getDocument(doc); + Gui::View3DInventor* view = dynamic_cast(viewDoc->getActiveView()); + if (view) { + Gui::View3DInventorViewer* viewer = view->getViewer(); + if (viewer->isEditing()) + return false; + } + if (Gui::Control().activeDialog()) + return false; + + return true; } //-------------------------------------------------------------------------------------- @@ -1120,7 +1130,8 @@ CmdMeshSmoothing::CmdMeshSmoothing() void CmdMeshSmoothing::activated(int iMsg) { - MeshGui::DlgSmoothing dlg(Gui::getMainWindow()); +#if 0 + MeshGui::SmoothingDialog dlg(Gui::getMainWindow()); if (dlg.exec() == QDialog::Accepted) { Gui::WaitCursor wc; openCommand("Mesh Smoothing"); @@ -1149,10 +1160,17 @@ void CmdMeshSmoothing::activated(int iMsg) } commitCommand(); } +#else + Gui::Control().showDialog(new MeshGui::TaskSmoothing()); +#endif } bool CmdMeshSmoothing::isActive(void) { +#if 1 + if (Gui::Control().activeDialog()) + return false; +#endif // Check for the selected mesh feature (all Mesh types) return getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0; } diff --git a/src/Mod/Mesh/Gui/DlgSmoothing.cpp b/src/Mod/Mesh/Gui/DlgSmoothing.cpp index 9efebc9ea9..4541d83e7c 100644 --- a/src/Mod/Mesh/Gui/DlgSmoothing.cpp +++ b/src/Mod/Mesh/Gui/DlgSmoothing.cpp @@ -23,17 +23,25 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include #endif #include "DlgSmoothing.h" #include "ui_DlgSmoothing.h" +#include "Selection.h" + +#include +#include +#include +#include +#include using namespace MeshGui; /* TRANSLATOR MeshGui::DlgSmoothing */ -DlgSmoothing::DlgSmoothing(QWidget* parent, Qt::WFlags fl) - : QDialog(parent, fl), ui(new Ui_DlgSmoothing()) +DlgSmoothing::DlgSmoothing(QWidget* parent) + : QWidget(parent), ui(new Ui_DlgSmoothing()) { ui->setupUi(this); bg = new QButtonGroup(this); @@ -92,4 +100,130 @@ DlgSmoothing::Smooth DlgSmoothing::method() const return DlgSmoothing::None; } +bool DlgSmoothing::smoothSelection() const +{ + return ui->checkBoxSelection->isChecked(); +} + +void DlgSmoothing::on_checkBoxSelection_toggled(bool on) +{ + /*emit*/ toggledSelection(on); +} + +// ------------------------------------------------ + +SmoothingDialog::SmoothingDialog(QWidget* parent, Qt::WFlags fl) + : QDialog(parent, fl) +{ + widget = new DlgSmoothing(this); + this->setWindowTitle(widget->windowTitle()); + + QVBoxLayout* hboxLayout = new QVBoxLayout(this); + QDialogButtonBox* buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + connect(buttonBox, SIGNAL(accepted()), + this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), + this, SLOT(reject())); + + hboxLayout->addWidget(widget); + hboxLayout->addWidget(buttonBox); +} + +SmoothingDialog::~SmoothingDialog() +{ +} + +// --------------------------------------- + +/* TRANSLATOR MeshGui::TaskSmoothing */ + +TaskSmoothing::TaskSmoothing() +{ + widget = new DlgSmoothing(); + Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), false, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); + + selection = new Selection(); + selection->setObjects(Gui::Selection().getSelectionEx(0, Mesh::Feature::getClassTypeId())); + Gui::TaskView::TaskGroup* tasksel = new Gui::TaskView::TaskGroup(); + tasksel->groupLayout()->addWidget(selection); + tasksel->hide(); + Content.push_back(tasksel); + + connect(widget, SIGNAL(toggledSelection(bool)), + tasksel, SLOT(setVisible(bool))); +} + +TaskSmoothing::~TaskSmoothing() +{ + // automatically deleted in the sub-class +} + +bool TaskSmoothing::accept() +{ + std::vector meshes = selection->getObjects(); + if (meshes.empty()) + return true; + + Gui::WaitCursor wc; + Gui::Command::openCommand("Mesh Smoothing"); + + bool hasSelection = false; + for (std::vector::const_iterator it = meshes.begin(); it != meshes.end(); ++it) { + Mesh::Feature* mesh = static_cast(*it); + std::vector selection; + if (widget->smoothSelection()) { + // clear the selection before editing the mesh to avoid + // to have coloured triangles when doing an 'undo' + const Mesh::MeshObject* mm = mesh->Mesh.getValuePtr(); + mm->getFacetsFromSelection(selection); + selection = mm->getPointsFromFacets(selection); + mm->clearFacetSelection(); + if (!selection.empty()) + hasSelection = true; + } + Mesh::MeshObject* mm = mesh->Mesh.startEditing(); + switch (widget->method()) { + case MeshGui::DlgSmoothing::Taubin: + { + MeshCore::TaubinSmoothing s(mm->getKernel()); + s.SetLambda(widget->lambdaStep()); + s.SetMicro(widget->microStep()); + if (widget->smoothSelection()) { + s.SmoothPoints(widget->iterations(), selection); + } + else { + s.Smooth(widget->iterations()); + } + } break; + case MeshGui::DlgSmoothing::Laplace: + { + MeshCore::LaplaceSmoothing s(mm->getKernel()); + s.SetLambda(widget->lambdaStep()); + if (widget->smoothSelection()) { + s.SmoothPoints(widget->iterations(), selection); + } + else { + s.Smooth(widget->iterations()); + } + } break; + default: + break; + } + mesh->Mesh.finishEditing(); + } + + if (widget->smoothSelection() && !hasSelection) { + Gui::Command::abortCommand(); + return false; + } + + Gui::Command::commitCommand(); + return true; +} + #include "moc_DlgSmoothing.cpp" diff --git a/src/Mod/Mesh/Gui/DlgSmoothing.h b/src/Mod/Mesh/Gui/DlgSmoothing.h index e3bf61d54c..fafccd3e13 100644 --- a/src/Mod/Mesh/Gui/DlgSmoothing.h +++ b/src/Mod/Mesh/Gui/DlgSmoothing.h @@ -25,13 +25,16 @@ #define MESHGUI_DLGSMOOTHING_H #include +#include +#include class QButtonGroup; namespace MeshGui { +class Selection; class Ui_DlgSmoothing; -class DlgSmoothing : public QDialog +class DlgSmoothing : public QWidget { Q_OBJECT @@ -42,21 +45,76 @@ public: Laplace }; - DlgSmoothing(QWidget* parent = 0, Qt::WFlags fl = 0); + DlgSmoothing(QWidget* parent = 0); ~DlgSmoothing(); int iterations() const; double lambdaStep() const; double microStep() const; Smooth method() const; + bool smoothSelection() const; private Q_SLOTS: void method_clicked(int); + void on_checkBoxSelection_toggled(bool); + +Q_SIGNALS: + void toggledSelection(bool); private: Ui_DlgSmoothing* ui; QButtonGroup* bg; }; +/** + * Embed the panel into a dialog. + */ +class MeshGuiExport SmoothingDialog : public QDialog +{ + Q_OBJECT + +public: + SmoothingDialog(QWidget* parent = 0, Qt::WFlags fl = 0); + ~SmoothingDialog(); + + int iterations() const + { return widget->iterations(); } + double lambdaStep() const + { return widget->lambdaStep(); } + double microStep() const + { return widget->microStep(); } + DlgSmoothing::Smooth method() const + { return widget->method(); } + bool smoothSelection() const + { return widget->smoothSelection(); } + +private: + DlgSmoothing* widget; +}; + +/** + * Embed the panel into a task dialog. + */ +class TaskSmoothing : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskSmoothing(); + ~TaskSmoothing(); + +public: + bool accept(); + + virtual QDialogButtonBox::StandardButtons getStandardButtons() const + { return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; } + virtual bool isAllowedAlterDocument(void) const + { return true; } + +private: + DlgSmoothing* widget; + Selection* selection; +}; + } #endif // MESHGUI_DLGSMOOTHING_H diff --git a/src/Mod/Mesh/Gui/DlgSmoothing.ui b/src/Mod/Mesh/Gui/DlgSmoothing.ui index 6914846394..69844eec0a 100644 --- a/src/Mod/Mesh/Gui/DlgSmoothing.ui +++ b/src/Mod/Mesh/Gui/DlgSmoothing.ui @@ -1,172 +1,130 @@ MeshGui::DlgSmoothing - + 0 0 - 242 - 251 + 210 + 227 Smoothing - + true - + - + - + Method - + - - - Method + + + Taubin + + + true - - - - - Taubin - - - true - - - - - - - Laplace - - - - - - - - Parameter + + + + Laplace - - - - - Iterations: - - - - - - - 1 - - - 4 - - - - - - - Lambda: - - - - - - - 4 - - - 1.000000000000000 - - - 0.001000000000000 - - - 0.630700000000000 - - - - - - - Mu: - - - - - - - 4 - - - 1.000000000000000 - - - 0.001000000000000 - - - 0.042400000000000 - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + Parameter + + + + + Iterations: + + + + + + + 1 + + + 4 + + + + + + + Lambda: + + + + + + + 4 + + + 1.000000000000000 + + + 0.001000000000000 + + + 0.630700000000000 + + + + + + + Mu: + + + + + + + 4 + + + 1.000000000000000 + + + 0.001000000000000 + + + 0.042400000000000 + + + + + + + Only selection + + + + - - - buttonBox - accepted() - MeshGui::DlgSmoothing - accept() - - - 94 - 191 - - - -3 - 193 - - - - - buttonBox - rejected() - MeshGui::DlgSmoothing - reject() - - - 190 - 193 - - - 219 - 151 - - - - + diff --git a/src/Mod/Mesh/Gui/MeshEditor.cpp b/src/Mod/Mesh/Gui/MeshEditor.cpp index 2f819554e7..11c2a2c201 100644 --- a/src/Mod/Mesh/Gui/MeshEditor.cpp +++ b/src/Mod/Mesh/Gui/MeshEditor.cpp @@ -40,15 +40,21 @@ # include # include # include +# include # include # include +# include #endif #include "MeshEditor.h" #include "SoFCMeshObject.h" +#include "SoPolygon.h" #include #include +#include +#include #include +#include #include #include @@ -278,8 +284,19 @@ void MeshFaceAddition::showMarker(SoPickedPoint* pp) return; // is a border facet picked? MeshCore::MeshFacet f = facets[face_index]; - if (!f.HasOpenEdge()) - return; + if (!f.HasOpenEdge()) { + // check if a neighbour facet is at the border + bool ok=false; + for (int i=0; i<3; i++) { + if (facets[f._aulNeighbours[i]].HasOpenEdge()) { + f = facets[f._aulNeighbours[i]]; + ok = true; + break; + } + } + if (!ok) + return; + } int point_index = -1; float distance = FLT_MAX; @@ -372,4 +389,326 @@ void MeshFaceAddition::addFacetCallback(void * ud, SoEventCallback * n) } } +// ---------------------------------------------------------------------- + +namespace MeshGui { + // for sorting of elements + struct NofFacetsCompare : public std::binary_function&, + const std::vector&, bool> + { + bool operator () (const std::vector &rclC1, + const std::vector &rclC2) + { + return rclC1.size() < rclC2.size(); + } + }; +} + +/* TRANSLATOR MeshGui::MeshFillHole */ + +MeshFillHole::MeshFillHole(MeshHoleFiller& hf, Gui::View3DInventor* parent) + : QObject(parent), myMesh(0), myNumPoints(0), myHoleFiller(hf) +{ + myBoundariesRoot = new SoSeparator; + myBoundariesRoot->ref(); + myBoundaryRoot = new SoSeparator; + myBoundaryRoot->ref(); + myBoundariesGroup = new SoSeparator(); + myBoundariesGroup->ref(); + myBridgeRoot = new SoSeparator; + myBridgeRoot->ref(); + + SoDrawStyle* pointStyle = new SoDrawStyle(); + pointStyle->style = SoDrawStyle::POINTS; + pointStyle->pointSize = 8.0f; + myBridgeRoot->addChild(pointStyle); + + SoBaseColor * markcol = new SoBaseColor; + markcol->rgb.setValue(1.0f, 1.0f, 0.0f); + SoPointSet* marker = new SoPointSet(); + myBridgeRoot->addChild(markcol); + + myVertex = new SoCoordinate3(); + myBridgeRoot->addChild(myVertex); + myBridgeRoot->addChild(new SoPointSet); +} + +MeshFillHole::~MeshFillHole() +{ + myBoundariesRoot->unref(); + myBoundariesGroup->unref(); + myBoundaryRoot->unref(); + myBridgeRoot->unref(); +} + +void MeshFillHole::startEditing(MeshGui::ViewProviderMesh* vp) +{ + this->myMesh = static_cast(vp->getObject()); + + Gui::View3DInventor* view = static_cast(parent()); + Gui::View3DInventorViewer* viewer = view->getViewer(); + viewer->setEditing(true); + //viewer->setRedirectToSceneGraph(true); + viewer->addEventCallback(SoEvent::getClassTypeId(), + MeshFillHole::fileHoleCallback, this); + myConnection = App::GetApplication().signalChangedObject.connect( + boost::bind(&MeshFillHole::slotChangedObject, this, _1, _2)); + + myBoundariesRoot->removeAllChildren(); + myBoundariesRoot->addChild(viewer->getHeadlight()); + myBoundariesRoot->addChild(viewer->getCamera()); + myBoundariesRoot->addChild(myBoundariesGroup); + myBoundaryRoot->removeAllChildren(); + myBoundaryRoot->addChild(viewer->getHeadlight()); + myBoundaryRoot->addChild(viewer->getCamera()); + createPolygons(); + static_cast(viewer->getSceneGraph())->addChild(myBridgeRoot); +} + +void MeshFillHole::finishEditing() +{ + Gui::View3DInventor* view = static_cast(parent()); + Gui::View3DInventorViewer* viewer = view->getViewer(); + viewer->setEditing(false); + //viewer->setRedirectToSceneGraph(false); + viewer->removeEventCallback(SoEvent::getClassTypeId(), + MeshFillHole::fileHoleCallback, this); + myConnection.disconnect(); + this->deleteLater(); + static_cast(viewer->getSceneGraph())->removeChild(myBridgeRoot); +} + +void MeshFillHole::closeBridge() +{ + // Do the hole-filling + Gui::WaitCursor wc; + TBoundary::iterator it = std::find(myPolygon.begin(), myPolygon.end(), myVertex1); + TBoundary::iterator jt = std::find(myPolygon.begin(), myPolygon.end(), myVertex2); + if (it != myPolygon.end() && jt != myPolygon.end()) { + // which iterator comes first + if (jt < it) + std::swap(it, jt); + // split the boundary into two loops and take the shorter one + std::list bounds; + TBoundary loop1, loop2; + loop1.insert(loop1.end(), myPolygon.begin(), it); + loop1.insert(loop1.end(), jt, myPolygon.end()); + loop2.insert(loop2.end(), it, jt); + // this happens when myVertex1 == myVertex2 + if (loop2.empty()) + bounds.push_back(loop1); + else if (loop1.size() < loop2.size()) + bounds.push_back(loop1); + else + bounds.push_back(loop2); + + App::Document* doc = myMesh->getDocument(); + doc->openTransaction("Bridge && Fill hole"); + Mesh::MeshObject* pMesh = myMesh->Mesh.startEditing(); + bool ok = myHoleFiller.fillHoles(*pMesh, bounds, myVertex1, myVertex2); + myMesh->Mesh.finishEditing(); + if (ok) + doc->commitTransaction(); + else + doc->abortTransaction(); + } +} + +void MeshFillHole::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop) +{ + if (&Obj == myMesh && strcmp(Prop.getName(),"Mesh") == 0) { + myBoundariesGroup->removeAllChildren(); + myVertex->point.setNum(0); + myNumPoints = 0; + myPolygon.clear(); + + createPolygons(); + } +} + +void MeshFillHole::createPolygons() +{ + Gui::WaitCursor wc; + myPolygons.clear(); + + SoPickStyle* pickStyle = new SoPickStyle(); + pickStyle->style = SoPickStyle::BOUNDING_BOX; + myBoundariesGroup->addChild(pickStyle); + myBoundaryRoot->addChild(pickStyle); + + // get mesh kernel + const MeshCore::MeshKernel & rMesh = this->myMesh->Mesh.getValue().getKernel(); + + // get the mesh boundaries as an array of point indices + std::list > borders; + MeshCore::MeshAlgorithm cAlgo(rMesh); + MeshCore::MeshPointIterator p_iter(rMesh); + cAlgo.GetMeshBorders(borders); + cAlgo.SplitBoundaryLoops(borders); + + // sort the borders in ascending order of the number of edges + borders.sort(NofFacetsCompare()); + + int32_t count=0; + for (std::list >::iterator it = + borders.begin(); it != borders.end(); ++it) { + if (it->front() == it->back()) + it->pop_back(); + count += it->size(); + } + + SoCoordinate3* coords = new SoCoordinate3(); + myBoundariesGroup->addChild(coords); + myBoundaryRoot->addChild(coords); + + coords->point.setNum(count); + int32_t index = 0; + for (std::list >::iterator it = + borders.begin(); it != borders.end(); ++it) { + SoPolygon* polygon = new SoPolygon(); + polygon->startIndex = index; + polygon->numVertices = it->size(); + myBoundariesGroup->addChild(polygon); + myPolygons[polygon] = *it; + for (std::vector::iterator jt = it->begin(); + jt != it->end(); ++jt) { + p_iter.Set(*jt); + coords->point.set1Value(index++,p_iter->x,p_iter->y,p_iter->z); + } + } +} + +SoNode* MeshFillHole::getPickedPolygon(const SoRayPickAction& action/*SoNode* root, const SbVec2s& pos, const SoQtViewer* viewer*/) const +{ + SoPolygon* poly = 0; + const SoPickedPointList & points = action.getPickedPointList(); + for (int i=0; i < points.getLength(); i++) { + const SoPickedPoint * point = points[i]; + if (point && point->getPath()->getTail()->getTypeId() == MeshGui::SoPolygon::getClassTypeId()) { + // we have something picked, now check if it was an SoPolygon node + SoPolygon* node = static_cast(point->getPath()->getTail()); + if (!poly) { + poly = node; + } + // check which polygon has less edges + else if (node->numVertices.getValue() < poly->numVertices.getValue()) { + poly = node; + } + } + } + + return poly; +} + +float MeshFillHole::findClosestPoint(const SbLine& ray, const TBoundary& polygon, + unsigned long& vertex_index, SbVec3f& closestPoint) const +{ + // now check which vertex of the polygon is closest to the ray + float minDist = FLT_MAX; + vertex_index = ULONG_MAX; + + const MeshCore::MeshKernel & rMesh = myMesh->Mesh.getValue().getKernel(); + const MeshCore::MeshPointArray& pts = rMesh.GetPoints(); + for (TBoundary::const_iterator it = polygon.begin(); it != polygon.end(); ++it) { + SbVec3f vertex; + const Base::Vector3f& v = pts[*it]; + vertex.setValue(v.x,v.y,v.z); + SbVec3f point = ray.getClosestPoint(vertex); + float distance = (vertex-point).sqrLength(); + if (distance < minDist) { + minDist = distance; + vertex_index = *it; + closestPoint = vertex; + } + } + + return minDist; +} + +void MeshFillHole::fileHoleCallback(void * ud, SoEventCallback * n) +{ + MeshFillHole* self = reinterpret_cast(ud); + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + + const SoEvent* ev = n->getEvent(); + if (ev->getTypeId() == SoLocation2Event::getClassTypeId()) { + n->setHandled(); + SoRayPickAction rp(view->getViewportRegion()); + rp.setPoint(ev->getPosition()); + rp.setPickAll(true); + if (self->myNumPoints == 0) + rp.apply(self->myBoundariesRoot); + else + rp.apply(self->myBoundaryRoot); + SoNode* node = self->getPickedPolygon(rp); + if (node) { + std::map::iterator it = self->myPolygons.find(node); + if (it != self->myPolygons.end()) { + // now check which vertex of the polygon is closest to the ray + unsigned long vertex_index; + SbVec3f closestPoint; + float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint); + if (minDist < 1.0f) { + if (self->myNumPoints == 0) + self->myVertex->point.set1Value(0, closestPoint); + else + self->myVertex->point.set1Value(1, closestPoint); + } + } + } + } + else if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) { + n->setHandled(); + const SoMouseButtonEvent * mbe = static_cast(ev); + if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { + } + else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP) { + if (self->myNumPoints > 1) + return; + SoRayPickAction rp(view->getViewportRegion()); + rp.setPoint(ev->getPosition()); + rp.setPickAll(true); + if (self->myNumPoints == 0) + rp.apply(self->myBoundariesRoot); + else + rp.apply(self->myBoundaryRoot); + SoNode* node = self->getPickedPolygon(rp); + if (node) { + std::map::iterator it = self->myPolygons.find(node); + if (it != self->myPolygons.end()) { + // now check which vertex of the polygon is closest to the ray + unsigned long vertex_index; + SbVec3f closestPoint; + float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint); + if (minDist < 1.0f) { + if (self->myNumPoints == 0) { + self->myBoundaryRoot->addChild(node); + self->myVertex->point.set1Value(0, closestPoint); + self->myNumPoints = 1; + self->myVertex1 = vertex_index; + } + else { + // myVertex2 can be equal to myVertex1 which does a full hole-filling + self->myBoundaryRoot->removeChild(node); + self->myVertex->point.set1Value(1, closestPoint); + self->myNumPoints = 2; + self->myVertex2 = vertex_index; + self->myPolygon = it->second; + QTimer::singleShot(300, self, SLOT(closeBridge())); + } + } + } + } + } + else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { + QMenu menu; + QAction* fin = menu.addAction(MeshFillHole::tr("Finish")); + QAction* act = menu.exec(QCursor::pos()); + if (act == fin) { + QTimer::singleShot(300, self, SLOT(finishEditing())); + } + } + } +} + #include "moc_MeshEditor.cpp" diff --git a/src/Mod/Mesh/Gui/MeshEditor.h b/src/Mod/Mesh/Gui/MeshEditor.h index c10a39470e..c7fb12f4df 100644 --- a/src/Mod/Mesh/Gui/MeshEditor.h +++ b/src/Mod/Mesh/Gui/MeshEditor.h @@ -25,15 +25,22 @@ #include #include +#include class SoCoordinate3; class SoFaceSet; class SoEventCallback; class SoPickedPoint; class SoQtViewer; +class SoGroup; +class SoSeparator; +class SoRayPickAction; +class SbLine; +class SbVec3f; namespace Gui { class View3DInventor; } - +namespace Mesh { class MeshObject; } +namespace Mesh { class Feature; } namespace MeshGui { class SoFCMeshPickNode; @@ -95,6 +102,69 @@ private: ViewProviderFace* faceView; }; +class MeshGuiExport MeshHoleFiller +{ +public: + MeshHoleFiller() + { + } + virtual ~MeshHoleFiller() + { + } + virtual bool fillHoles(Mesh::MeshObject& mesh, const std::list >& boundaries, + unsigned long v1, unsigned long v2) + { + return false; + } +}; + +/** + * Display data of a mesh kernel. + * \author Werner Mayer + */ +class MeshGuiExport MeshFillHole : public QObject +{ + Q_OBJECT + +public: + MeshFillHole(MeshHoleFiller& hf, Gui::View3DInventor* parent); + virtual ~MeshFillHole(); + + void startEditing(ViewProviderMesh*); + +public Q_SLOTS: + void finishEditing(); + +private Q_SLOTS: + void closeBridge(); + +private: + typedef std::vector TBoundary; + typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection; + + static void fileHoleCallback(void * ud, SoEventCallback * n); + void createPolygons(); + SoNode* getPickedPolygon(const SoRayPickAction& action) const; + float findClosestPoint(const SbLine& ray, const TBoundary& polygon, + unsigned long&, SbVec3f&) const; + void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop); + +private: + SoSeparator* myBoundariesRoot; + SoGroup* myBoundariesGroup; + SoSeparator* myBoundaryRoot; + SoSeparator* myBridgeRoot; + SoCoordinate3* myVertex; + std::map myPolygons; + Mesh::Feature* myMesh; + int myNumPoints; + unsigned long myVertex1; + unsigned long myVertex2; + TBoundary myPolygon; + MeshHoleFiller& myHoleFiller; + Connection myConnection; +}; + } // namespace MeshGui diff --git a/src/Mod/Mesh/Gui/MeshSelection.cpp b/src/Mod/Mesh/Gui/MeshSelection.cpp new file mode 100644 index 0000000000..a724f96ce4 --- /dev/null +++ b/src/Mod/Mesh/Gui/MeshSelection.cpp @@ -0,0 +1,467 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +#endif + +#include "MeshSelection.h" +#include "ViewProvider.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace MeshGui; + +#define CROSS_WIDTH 16 +#define CROSS_HEIGHT 16 +#define CROSS_HOT_X 7 +#define CROSS_HOT_Y 7 + +unsigned char MeshSelection::cross_bitmap[] = { + 0xc0, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x7f, 0xfe, 0x01, 0x80, + 0x01, 0x80, 0x7f, 0xfe, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xc0, 0x03 +}; + +unsigned char MeshSelection::cross_mask_bitmap[] = { + 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, + 0xc0, 0x03, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xc0, 0x03, + 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03 +}; + +MeshSelection::MeshSelection() + : onlyPointToUserTriangles(false), onlyVisibleTriangles(false), _activeCB(0) +{ +} + +MeshSelection::~MeshSelection() +{ + if (_activeCB) { + Gui::View3DInventorViewer* viewer = this->getViewer(); + if (viewer) + stopInteractiveCallback(viewer); + } +} + +void MeshSelection::setObjects(const std::vector& obj) +{ + meshObjects = obj; +} + +std::vector MeshSelection::getObjects() const +{ + std::vector objs; + if (!meshObjects.empty()) { + for (std::vector::iterator it = meshObjects.begin(); it != meshObjects.end(); ++it) { + App::DocumentObject* obj = it->getObject(); + if (obj) { + objs.push_back(obj); + } + } + } + // get all objects of the active document + else { + App::Document* doc = App::GetApplication().getActiveDocument(); + if (doc) + objs = doc->getObjectsOfType(Mesh::Feature::getClassTypeId()); + } + + return objs; +} + +std::list MeshSelection::getViewProviders() const +{ + std::vector objs = getObjects(); + std::list vps; + for (std::vector::iterator it = objs.begin(); it != objs.end(); ++it) { + if ((*it)->isDerivedFrom(Mesh::Feature::getClassTypeId())) { + Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(*it); + if (vp->isVisible()) + vps.push_back(static_cast(vp)); + } + } + + return vps; +} + +Gui::View3DInventorViewer* MeshSelection::getViewer() const +{ + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (!doc) return 0; + Gui::MDIView* view = doc->getActiveView(); + if (view && view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); + return viewer; + } + + return 0; +} + +void MeshSelection::startInteractiveCallback(Gui::View3DInventorViewer* viewer,SoEventCallbackCB *cb) +{ + if (this->_activeCB) + return; + viewer->setEditing(true); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), cb, this); + this->_activeCB = cb; +} + +void MeshSelection::stopInteractiveCallback(Gui::View3DInventorViewer* viewer) +{ + if (!this->_activeCB) + return; + if (viewer->isEditing()) { + viewer->setEditing(false); + viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), this->_activeCB, this); + this->_activeCB = 0; + } +} + +void MeshSelection::prepareBrushSelection(bool add) +{ + // a rubberband to select a rectangle area of the meshes + Gui::View3DInventorViewer* viewer = this->getViewer(); + if (viewer) { + stopInteractiveCallback(viewer); + startInteractiveCallback(viewer, selectGLCallback); + // set cross cursor + Gui::BrushSelection* brush = new Gui::BrushSelection(); + brush->setColor(1.0f,0.0f,0.0f); + brush->setLineWidth(3.0f); + viewer->navigationStyle()->startSelection(brush); + SoQtCursor::CustomCursor custom; + custom.dim.setValue(CROSS_WIDTH, CROSS_HEIGHT); + custom.hotspot.setValue(CROSS_HOT_X, CROSS_HOT_Y); + custom.bitmap = cross_bitmap; + custom.mask = cross_mask_bitmap; + viewer->setComponentCursor(SoQtCursor(&custom)); + this->addToSelection = add; + } +} + +void MeshSelection::startSelection() +{ + prepareBrushSelection(true); +} + +void MeshSelection::startDeselection() +{ + prepareBrushSelection(false); +} + +void MeshSelection::fullSelection() +{ + // select the complete meshes + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + Mesh::Feature* mf = static_cast((*it)->getObject()); + const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); + std::vector faces(mo->countFacets()); + std::generate(faces.begin(), faces.end(), Base::iotaGen(0)); + (*it)->addSelection(faces); + } +} + +void MeshSelection::clearSelection() +{ + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + (*it)->clearSelection(); + } +} + +bool MeshSelection::deleteSelection() +{ + // delete all selected faces + bool selected = false; + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + Mesh::Feature* mf = static_cast((*it)->getObject()); + unsigned long ct = MeshCore::MeshAlgorithm(mf->Mesh.getValue().getKernel()). + CountFacetFlag(MeshCore::MeshFacet::SELECTED); + if (ct > 0) { + selected = true; + break; + } + } + if (!selected) + return false; // nothing todo + + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + (*it)->deleteSelection(); + } + + return true; +} + +void MeshSelection::invertSelection() +{ + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + Mesh::Feature* mf = static_cast((*it)->getObject()); + const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); + const MeshCore::MeshFacetArray& faces = mo->getKernel().GetFacets(); + unsigned long num_notsel = std::count_if(faces.begin(), faces.end(), + std::bind2nd(MeshCore::MeshIsNotFlag(), + MeshCore::MeshFacet::SELECTED)); + std::vector notselect; + notselect.reserve(num_notsel); + MeshCore::MeshFacetArray::_TConstIterator beg = faces.begin(); + MeshCore::MeshFacetArray::_TConstIterator end = faces.end(); + for (MeshCore::MeshFacetArray::_TConstIterator jt = beg; jt != end; ++jt) { + if (!jt->IsFlag(MeshCore::MeshFacet::SELECTED)) + notselect.push_back(jt-beg); + } + (*it)->setSelection(notselect); + } +} + +void MeshSelection::selectComponent(int size) +{ + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + Mesh::Feature* mf = static_cast((*it)->getObject()); + const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); + + std::vector > segm; + MeshCore::MeshComponents comp(mo->getKernel()); + comp.SearchForComponents(MeshCore::MeshComponents::OverEdge,segm); + + std::vector faces; + for (std::vector >::iterator jt = segm.begin(); jt != segm.end(); ++jt) { + if (jt->size() < (unsigned long)size) + faces.insert(faces.end(), jt->begin(), jt->end()); + } + + (*it)->addSelection(faces); + } +} + +void MeshSelection::deselectComponent(int size) +{ + std::list views = getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + Mesh::Feature* mf = static_cast((*it)->getObject()); + const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); + + std::vector > segm; + MeshCore::MeshComponents comp(mo->getKernel()); + comp.SearchForComponents(MeshCore::MeshComponents::OverEdge,segm); + + std::vector faces; + for (std::vector >::iterator jt = segm.begin(); jt != segm.end(); ++jt) { + if (jt->size() > (unsigned long)size) + faces.insert(faces.end(), jt->begin(), jt->end()); + } + + (*it)->removeSelection(faces); + } +} + +void MeshSelection::selectTriangle() +{ + this->addToSelection = true; + + Gui::View3DInventorViewer* viewer = this->getViewer(); + if (viewer) { + viewer->setEditingCursor(QCursor(Qt::OpenHandCursor)); + stopInteractiveCallback(viewer); + startInteractiveCallback(viewer, pickFaceCallback); + } +} + +void MeshSelection::deselectTriangle() +{ + this->addToSelection = false; + + Gui::View3DInventorViewer* viewer = this->getViewer(); + if (viewer) { + viewer->setEditingCursor(QCursor(Qt::OpenHandCursor)); + stopInteractiveCallback(viewer); + startInteractiveCallback(viewer, pickFaceCallback); + } +} + +void MeshSelection::setCheckOnlyPointToUserTriangles(bool on) +{ + onlyPointToUserTriangles = on; +} + +void MeshSelection::setCheckOnlyVisibleTriangles(bool on) +{ + onlyVisibleTriangles = on; +} + +void MeshSelection::setAddComponentOnClick(bool on) +{ + addComponent = on; +} + +void MeshSelection::setRemoveComponentOnClick(bool on) +{ + removeComponent = on; +} + +void MeshSelection::selectGLCallback(void * ud, SoEventCallback * n) +{ + // When this callback function is invoked we must leave the edit mode + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + MeshSelection* self = reinterpret_cast(ud); + self->stopInteractiveCallback(view); + n->setHandled(); + std::vector polygon = view->getGLPolygon(); + if (polygon.size() < 3) + return; + if (polygon.front() != polygon.back()) + polygon.push_back(polygon.front()); + + SbVec3f pnt, dir; + view->getNearPlane(pnt, dir); + Base::Vector3f point (pnt[0],pnt[1],pnt[2]); + Base::Vector3f normal(dir[0],dir[1],dir[2]); + + std::list views = self->getViewProviders(); + for (std::list::iterator it = views.begin(); it != views.end(); ++it) { + ViewProviderMesh* vp = static_cast(*it); + + std::vector faces; + const Mesh::MeshObject& mesh = static_cast((*it)->getObject())->Mesh.getValue(); + const MeshCore::MeshKernel& kernel = mesh.getKernel(); + + // simply get all triangles under the polygon + vp->getFacetsFromPolygon(polygon, *view, true, faces); + if (self->onlyVisibleTriangles) { + const SbVec2s& sz = view->getViewportRegion().getWindowSize(); + short width,height; sz.getValue(width,height); + std::vector pixelPoly = view->getPolygon(); + SbBox2s rect; + for (std::vector::iterator it = pixelPoly.begin(); it != pixelPoly.end(); ++it) { + const SbVec2s& p = *it; + rect.extendBy(SbVec2s(p[0],height-p[1])); + } + std::vector rf; rf.swap(faces); + std::vector vf = vp->getVisibleFacetsAfterZoom + (rect, view->getViewportRegion(), view->getCamera()); + + // get common facets of the viewport and the visible one + std::sort(vf.begin(), vf.end()); + std::sort(rf.begin(), rf.end()); + std::back_insert_iterator > biit(faces); + std::set_intersection(vf.begin(), vf.end(), rf.begin(), rf.end(), biit); + } + + // if set filter out all triangles which do not point into user direction + if (self->onlyPointToUserTriangles) { + std::vector screen; + screen.reserve(faces.size()); + MeshCore::MeshFacetIterator it_f(kernel); + for (std::vector::iterator it = faces.begin(); it != faces.end(); ++it) { + it_f.Set(*it); + if (it_f->GetNormal() * normal > 0.0f) { + screen.push_back(*it); + } + } + + faces.swap(screen); + } + + if (self->addToSelection) + vp->addSelection(faces); + else + vp->removeSelection(faces); + } + + view->render(); +} + +void MeshSelection::pickFaceCallback(void * ud, SoEventCallback * n) +{ + // handle only mouse button events + if (n->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) { + const SoMouseButtonEvent * mbe = static_cast(n->getEvent()); + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + + // Mark all incoming mouse button events as handled, especially, to deactivate the selection node + n->getAction()->setHandled(); + if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { + const SoPickedPoint * point = n->getPickedPoint(); + if (point == NULL) { + Base::Console().Message("No facet picked.\n"); + return; + } + + n->setHandled(); + + // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is + // really from the mesh we render and not from any other geometry + Gui::ViewProvider* vp = static_cast(view->getViewProviderByPath(point->getPath())); + if (!vp || !vp->getTypeId().isDerivedFrom(ViewProviderMesh::getClassTypeId())) + return; + ViewProviderMesh* mesh = static_cast(vp); + MeshSelection* self = reinterpret_cast(ud); + std::list views = self->getViewProviders(); + if (std::find(views.begin(), views.end(), mesh) == views.end()) + return; + const SoDetail* detail = point->getDetail(/*mesh->getShapeNode()*/); + if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { + // get the boundary to the picked facet + unsigned long uFacet = static_cast(detail)->getFaceIndex(); + if (self->addToSelection) { + if (self->addComponent) + mesh->selectComponent(uFacet); + else + mesh->selectFacet(uFacet); + } + else { + if (self->removeComponent) + mesh->deselectComponent(uFacet); + else + mesh->deselectFacet(uFacet); + } + } + } + } +} diff --git a/src/Mod/Mesh/Gui/MeshSelection.h b/src/Mod/Mesh/Gui/MeshSelection.h new file mode 100644 index 0000000000..e2857ba025 --- /dev/null +++ b/src/Mod/Mesh/Gui/MeshSelection.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_MESHSELECTION_H +#define MESHGUI_MESHSELECTION_H + +#include +#include +#include +#include +#include +#include + +namespace Gui { + class View3DInventorViewer; +} + +namespace MeshGui { + +class ViewProviderMesh; + +class MeshGuiExport MeshSelection +{ +public: + MeshSelection(); + ~MeshSelection(); + + void startSelection(); + void startDeselection(); + bool deleteSelection(); + void fullSelection(); + void clearSelection(); + void invertSelection(); + + void selectComponent(int); + void deselectComponent(int); + void selectTriangle(); + void deselectTriangle(); + + void setCheckOnlyPointToUserTriangles(bool); + void setCheckOnlyVisibleTriangles(bool); + void setAddComponentOnClick(bool); + void setRemoveComponentOnClick(bool); + void setObjects(const std::vector&); + std::vector getObjects() const; + +private: + std::list getViewProviders() const; + Gui::View3DInventorViewer* getViewer() const; + void startInteractiveCallback(Gui::View3DInventorViewer* viewer,SoEventCallbackCB *cb); + void stopInteractiveCallback(Gui::View3DInventorViewer* viewer); + void prepareBrushSelection(bool); + + static void selectGLCallback(void * ud, SoEventCallback * n); + static void pickFaceCallback(void * ud, SoEventCallback * n); + +private: + bool onlyPointToUserTriangles, onlyVisibleTriangles; + bool addToSelection, addComponent, removeComponent; + SoEventCallbackCB *_activeCB; + mutable std::vector meshObjects; + + static unsigned char cross_bitmap[]; + static unsigned char cross_mask_bitmap[]; +}; + +} + +#endif // MESHGUI_MESHSELECTION_H diff --git a/src/Mod/Mesh/Gui/RemoveComponents.cpp b/src/Mod/Mesh/Gui/RemoveComponents.cpp index 708eb8b4e6..a66e3f500d 100644 --- a/src/Mod/Mesh/Gui/RemoveComponents.cpp +++ b/src/Mod/Mesh/Gui/RemoveComponents.cpp @@ -27,12 +27,19 @@ # include # include # include +# include +# include # include # include # include # include +# include # include +# include # include +# include +# include +# include #endif #include "RemoveComponents.h" @@ -42,9 +49,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -56,26 +66,9 @@ using namespace MeshGui; -#define CROSS_WIDTH 16 -#define CROSS_HEIGHT 16 -#define CROSS_HOT_X 7 -#define CROSS_HOT_Y 7 - -static unsigned char cross_bitmap[] = { - 0xc0, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, - 0x40, 0x02, 0x40, 0x02, 0x7f, 0xfe, 0x01, 0x80, - 0x01, 0x80, 0x7f, 0xfe, 0x40, 0x02, 0x40, 0x02, - 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xc0, 0x03 -}; - -static unsigned char cross_mask_bitmap[] = { - 0xc0,0x03,0xc0,0x03,0xc0,0x03,0xc0,0x03,0xc0,0x03,0xc0,0x03,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xc0,0x03,0xc0,0x03,0xc0,0x03,0xc0,0x03,0xc0,0x03, - 0xc0,0x03 -}; RemoveComponents::RemoveComponents(QWidget* parent, Qt::WFlags fl) - : QWidget(parent, fl), _interactiveMode(0) + : QWidget(parent, fl) { ui = new Ui_RemoveComponents; ui->setupUi(this); @@ -83,6 +76,9 @@ RemoveComponents::RemoveComponents(QWidget* parent, Qt::WFlags fl) ui->spSelectComp->setValue(10); ui->spDeselectComp->setRange(1, INT_MAX); ui->spDeselectComp->setValue(10); + + meshSel.setCheckOnlyVisibleTriangles(ui->visibleTriangles->isChecked()); + meshSel.setCheckOnlyPointToUserTriangles(ui->screenTriangles->isChecked()); } RemoveComponents::~RemoveComponents() @@ -101,372 +97,266 @@ void RemoveComponents::changeEvent(QEvent *e) void RemoveComponents::on_selectRegion_clicked() { - // a rubberband to select a rectangle area of the meshes - this->selectRegion = true; - Gui::View3DInventorViewer* viewer = this->getViewer(); - if (viewer) { - stopInteractiveCallback(viewer); - startInteractiveCallback(viewer, selectGLCallback); - // set cross cursor - viewer->startSelection(Gui::View3DInventorViewer::Lasso); - SoQtCursor::CustomCursor custom; - custom.dim.setValue(CROSS_WIDTH, CROSS_HEIGHT); - custom.hotspot.setValue(CROSS_HOT_X, CROSS_HOT_Y); - custom.bitmap = cross_bitmap; - custom.mask = cross_mask_bitmap; - viewer->setComponentCursor(SoQtCursor(&custom)); - } + meshSel.startSelection(); } void RemoveComponents::on_deselectRegion_clicked() { - // a rubberband to deselect a rectangle area of the meshes - this->selectRegion = false; - Gui::View3DInventorViewer* viewer = this->getViewer(); - if (viewer) { - stopInteractiveCallback(viewer); - startInteractiveCallback(viewer, selectGLCallback); - // set cross cursor - viewer->startSelection(Gui::View3DInventorViewer::Lasso); - SoQtCursor::CustomCursor custom; - custom.dim.setValue(CROSS_WIDTH, CROSS_HEIGHT); - custom.hotspot.setValue(CROSS_HOT_X, CROSS_HOT_Y); - custom.bitmap = cross_bitmap; - custom.mask = cross_mask_bitmap; - viewer->setComponentCursor(SoQtCursor(&custom)); - } + meshSel.startDeselection(); } void RemoveComponents::on_selectAll_clicked() { // select the complete meshes - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - Mesh::Feature* mf = static_cast((*it)->getObject()); - const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); - std::vector faces(mo->countFacets()); - std::generate(faces.begin(), faces.end(), Base::iotaGen(0)); - (*it)->addSelection(faces); - } + meshSel.fullSelection(); } void RemoveComponents::on_deselectAll_clicked() { // deselect all meshes - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - (*it)->clearSelection(); - } + meshSel.clearSelection(); } void RemoveComponents::on_selectComponents_clicked() { // select components upto a certain size int size = ui->spSelectComp->value(); - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - Mesh::Feature* mf = static_cast((*it)->getObject()); - const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); - - std::vector > segm; - MeshCore::MeshComponents comp(mo->getKernel()); - comp.SearchForComponents(MeshCore::MeshComponents::OverEdge,segm); - - std::vector faces; - for (std::vector >::iterator jt = segm.begin(); jt != segm.end(); ++jt) { - if (jt->size() < (unsigned long)size) - faces.insert(faces.end(), jt->begin(), jt->end()); - } - - (*it)->addSelection(faces); - } + meshSel.selectComponent(size); } void RemoveComponents::on_deselectComponents_clicked() { // deselect components from a certain size on int size = ui->spDeselectComp->value(); - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - Mesh::Feature* mf = static_cast((*it)->getObject()); - const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); + meshSel.deselectComponent(size); +} - std::vector > segm; - MeshCore::MeshComponents comp(mo->getKernel()); - comp.SearchForComponents(MeshCore::MeshComponents::OverEdge,segm); - - std::vector faces; - for (std::vector >::iterator jt = segm.begin(); jt != segm.end(); ++jt) { - if (jt->size() > (unsigned long)size) - faces.insert(faces.end(), jt->begin(), jt->end()); - } - - (*it)->removeSelection(faces); - } +void RemoveComponents::on_visibleTriangles_toggled(bool on) +{ + meshSel.setCheckOnlyVisibleTriangles(on); +} + +void RemoveComponents::on_screenTriangles_toggled(bool on) +{ + meshSel.setCheckOnlyPointToUserTriangles(on); +} + +void RemoveComponents::on_cbSelectComp_toggled(bool on) +{ + meshSel.setAddComponentOnClick(on); +} + +void RemoveComponents::on_cbDeselectComp_toggled(bool on) +{ + meshSel.setRemoveComponentOnClick(on); } void RemoveComponents::deleteSelection() { - // delete all selected faces - bool selected = false; Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - Mesh::Feature* mf = static_cast((*it)->getObject()); - unsigned long ct = MeshCore::MeshAlgorithm(mf->Mesh.getValue().getKernel()). - CountFacetFlag(MeshCore::MeshFacet::SELECTED); - if (ct > 0) { - selected = true; - break; - } - } - if (!selected) return; // nothing todo - + // delete all selected faces doc->openCommand("Delete selection"); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - (*it)->deleteSelection(); - } - doc->commitCommand(); + bool ok = meshSel.deleteSelection(); + if (!ok) + doc->abortCommand(); + else + doc->commitCommand(); } void RemoveComponents::invertSelection() { - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - Mesh::Feature* mf = static_cast((*it)->getObject()); - const Mesh::MeshObject* mo = mf->Mesh.getValuePtr(); - const MeshCore::MeshFacetArray& faces = mo->getKernel().GetFacets(); - unsigned long num_notsel = std::count_if(faces.begin(), faces.end(), - std::bind2nd(MeshCore::MeshIsNotFlag(), - MeshCore::MeshFacet::SELECTED)); - std::vector notselect; - notselect.reserve(num_notsel); - MeshCore::MeshFacetArray::_TConstIterator beg = faces.begin(); - MeshCore::MeshFacetArray::_TConstIterator end = faces.end(); - for (MeshCore::MeshFacetArray::_TConstIterator jt = beg; jt != end; ++jt) { - if (!jt->IsFlag(MeshCore::MeshFacet::SELECTED)) - notselect.push_back(jt-beg); - } - (*it)->setSelection(notselect); - } + meshSel.invertSelection(); } void RemoveComponents::on_selectTriangle_clicked() { - // a rubberband to select a rectangle area of the meshes - this->selectRegion = true; - Gui::View3DInventorViewer* viewer = this->getViewer(); - if (viewer) { - stopInteractiveCallback(viewer); - startInteractiveCallback(viewer, pickFaceCallback); - } + meshSel.selectTriangle(); + meshSel.setAddComponentOnClick(ui->cbSelectComp->isChecked()); } void RemoveComponents::on_deselectTriangle_clicked() { - // a rubberband to select a rectangle area of the meshes - this->selectRegion = false; - Gui::View3DInventorViewer* viewer = this->getViewer(); - if (viewer) { - stopInteractiveCallback(viewer); - startInteractiveCallback(viewer, pickFaceCallback); - } + meshSel.deselectTriangle(); + meshSel.setRemoveComponentOnClick(ui->cbDeselectComp->isChecked()); } void RemoveComponents::reject() { - if (_interactiveMode) { - Gui::View3DInventorViewer* viewer = this->getViewer(); - if (viewer) - stopInteractiveCallback(viewer); - } - on_deselectAll_clicked(); + // deselect all meshes + meshSel.clearSelection(); } -std::list RemoveComponents::getViewProviders(const Gui::Document* doc) const +void RemoveComponents::paintSelection() { - std::list vps; - std::vector mesh = doc->getDocument()->getObjectsOfType(); - for (std::vector::iterator it = mesh.begin(); it != mesh.end(); ++it) { - Gui::ViewProvider* vp = doc->getViewProvider(*it); - if (vp->isVisible()) - vps.push_back(static_cast(vp)); - } - - return vps; +#if 0 + SoAnnotation* hudRoot = new SoAnnotation; + hudRoot->ref(); + + SoOrthographicCamera* hudCam = new SoOrthographicCamera(); + hudCam->viewportMapping = SoCamera::LEAVE_ALONE; + // Set the position in the window. + // [0, 0] is in the center of the screen. + // + SoTranslation* hudTrans = new SoTranslation; + hudTrans->translation.setValue(-1.0f, -1.0f, 0.0f); + + QImage image(100,100,QImage::Format_ARGB32_Premultiplied); + image.fill(0x00000000); + SoSFImage sfimage; + Gui::BitmapFactory().convert(image, sfimage); + SoImage* hudImage = new SoImage(); + hudImage->image = sfimage; + + // Assemble the parts... + // + hudRoot->addChild(hudCam); + hudRoot->addChild(hudTrans); + hudRoot->addChild(hudImage); + + Gui::View3DInventorViewer* viewer = this->getViewer(); + static_cast(viewer->getSceneGraph())->addChild(hudRoot); + + QWidget* gl = viewer->getGLWidget(); + DrawingPlane pln(hudImage->image, viewer, gl); + gl->installEventFilter(&pln); + QEventLoop loop; + QObject::connect(&pln, SIGNAL(emitSelection()), &loop, SLOT(quit())); + loop.exec(); + static_cast(viewer->getSceneGraph())->removeChild(hudRoot); +#endif } -Gui::View3DInventorViewer* RemoveComponents::getViewer() const +// --------------------------------------- + +DrawingPlane::DrawingPlane(SoSFImage& data, SoQtViewer* s, QWidget* view) + : QObject(), data(data), glView(view), soqt(s), image(view->size(), QImage::Format_ARGB32) { - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return 0; - Gui::MDIView* view = doc->getActiveView(); - if (view && view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { - Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); - return viewer; - } + image.fill(qRgba(255, 255, 255, 0)); + + myPenWidth = 50; - return 0; + QRgb p = qRgba(255,255,0,0); + int q = ((p << 16) & 0xff0000) | ((p >> 16) & 0xff) | (p & 0xff00ff00); + int r = qRed(q); + int g = qGreen(q); + int b = qBlue(q); + myPenColor = qRgb(r,g,b);//Qt::yellow; + myRadius = 5.0f; } -void RemoveComponents::startInteractiveCallback(Gui::View3DInventorViewer* viewer,SoEventCallbackCB *cb) +DrawingPlane::~DrawingPlane() { - if (this->_interactiveMode) - return; - viewer->setEditing(true); - viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), cb, this); - this->_interactiveMode = cb; } -void RemoveComponents::stopInteractiveCallback(Gui::View3DInventorViewer* viewer) +void DrawingPlane::changeRadius(double radius) { - if (!this->_interactiveMode) - return; - if (viewer->isEditing()) { - viewer->setEditing(false); - viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), this->_interactiveMode, this); - this->_interactiveMode = 0; - } -} + this->myRadius = (double)radius; +} -void RemoveComponents::selectGLCallback(void * ud, SoEventCallback * n) -{ - // When this callback function is invoked we must leave the edit mode - Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); - RemoveComponents* that = reinterpret_cast(ud); - that->stopInteractiveCallback(view); - n->setHandled(); - std::vector polygon = view->getGLPolygon(); - if (polygon.size() < 3) - return; - if (polygon.front() != polygon.back()) - polygon.push_back(polygon.front()); +void DrawingPlane::mousePressEvent(QMouseEvent *event) +{ + // Calculate the given radius from mm into px + const SbViewportRegion& vp = soqt->getViewportRegion(); + float fRatio = vp.getViewportAspectRatio(); + const SbVec2s& sp = vp.getViewportSizePixels(); + float dX, dY; vp.getViewportSize().getValue(dX, dY); + SbViewVolume vv = soqt->getCamera()->getViewVolume(fRatio); + + SbVec3f p1(0,0,0); + SbVec3f p2(0,this->myRadius,0); + vv.projectToScreen(p1, p1); + vv.projectToScreen(p2, p2); + + if (fRatio > 1.0f) { + p1[0] = (p1[0] - 0.5f*dX) / fRatio + 0.5f*dX; + p2[0] = (p2[0] - 0.5f*dX) / fRatio + 0.5f*dX; + } + else if (fRatio < 1.0f) { + p1[1] = (p1[1] - 0.5f*dY) * fRatio + 0.5f*dY; + p2[1] = (p2[1] - 0.5f*dY) * fRatio + 0.5f*dY; + } - SbVec3f pnt, dir; - view->getNearPlane(pnt, dir); - Base::Vector3f point (pnt[0],pnt[1],pnt[2]); - Base::Vector3f normal(dir[0],dir[1],dir[2]); + int x1 = p1[0] * sp[0]; + int y1 = p1[1] * sp[1]; + int x2 = p2[0] * sp[0]; + int y2 = p2[1] * sp[1]; - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = that->getViewProviders(doc); - for (std::list::iterator it = views.begin(); it != views.end(); ++it) { - ViewProviderMesh* vp = static_cast(*it); + //myPenWidth = 2*abs(y1-y2); + + if (event->button() == Qt::LeftButton) { + lastPoint = event->pos(); + scribbling = true; + } +} + +void DrawingPlane::mouseMoveEvent(QMouseEvent *event) +{ + if ((event->buttons() & Qt::LeftButton) && scribbling) { + const QPoint& pos = event->pos(); + drawLineTo(pos); - std::vector faces; - const Mesh::MeshObject& mesh = static_cast((*it)->getObject())->Mesh.getValue(); - const MeshCore::MeshKernel& kernel = mesh.getKernel(); - - // simply get all triangles under the polygon - vp->getFacetsFromPolygon(polygon, *view, true, faces); - if (that->ui->frontTriangles->isChecked()) { - const SbVec2s& sz = view->getViewportRegion().getWindowSize(); - short width,height; sz.getValue(width,height); - std::vector pixelPoly = view->getPolygon(); - SbBox2s rect; - for (std::vector::iterator it = pixelPoly.begin(); it != pixelPoly.end(); ++it) { - const SbVec2s& p = *it; - rect.extendBy(SbVec2s(p[0],height-p[1])); - } - std::vector rf; rf.swap(faces); - std::vector vf = vp->getVisibleFacetsAfterZoom - (rect, view->getViewportRegion(), view->getCamera()); - - // get common facets of the viewport and the visible one - std::sort(vf.begin(), vf.end()); - std::sort(rf.begin(), rf.end()); - std::back_insert_iterator > biit(faces); - std::set_intersection(vf.begin(), vf.end(), rf.begin(), rf.end(), biit); - } - - // if set filter out all triangles which do not point into user direction - if (that->ui->screenTriangles->isChecked()) { - std::vector screen; - screen.reserve(faces.size()); - MeshCore::MeshFacetIterator it_f(kernel); - for (std::vector::iterator it = faces.begin(); it != faces.end(); ++it) { - it_f.Set(*it); - if (it_f->GetNormal() * normal > 0.0f) { - screen.push_back(*it); - } - } - - faces.swap(screen); - } - - if (that->selectRegion) - vp->addSelection(faces); - else - vp->removeSelection(faces); - } - - view->render(); -} - -void RemoveComponents::pickFaceCallback(void * ud, SoEventCallback * n) -{ - // handle only mouse button events - if (n->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) { - const SoMouseButtonEvent * mbe = static_cast(n->getEvent()); - Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); - - // Mark all incoming mouse button events as handled, especially, to deactivate the selection node - n->getAction()->setHandled(); - if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { - const SoPickedPoint * point = n->getPickedPoint(); - if (point == NULL) { - Base::Console().Message("No facet picked.\n"); - return; - } - - n->setHandled(); - - // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is - // really from the mesh we render and not from any other geometry - Gui::ViewProvider* vp = static_cast(view->getViewProviderByPath(point->getPath())); - if (!vp || !vp->getTypeId().isDerivedFrom(ViewProviderMesh::getClassTypeId())) - return; - ViewProviderMesh* that = static_cast(vp); - RemoveComponents* dlg = reinterpret_cast(ud); - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (!doc) return; - std::list views = dlg->getViewProviders(doc); - if (std::find(views.begin(), views.end(), that) == views.end()) - return; - const SoDetail* detail = point->getDetail(/*that->getShapeNode()*/); - if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { - // get the boundary to the picked facet - unsigned long uFacet = static_cast(detail)->getFaceIndex(); - std::vector faces; faces.push_back(uFacet); - if (dlg->selectRegion) { - if (dlg->ui->cbSelectComp->isChecked()) - that->selectComponent(uFacet); - else - that->selectFacet(uFacet); - } - else { - if (dlg->ui->cbDeselectComp->isChecked()) - that->deselectComponent(uFacet); - else - that->removeSelection(faces); - } - } + // filter out some points + if (selection.isEmpty()) { + selection << pos; + } + else { + const QPoint& top = selection.last(); + if (abs(top.x()-pos.x()) > 20 || + abs(top.y()-pos.y()) > 20) + selection << pos; } } } -// --------------------------------------- +void DrawingPlane::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && scribbling) { + drawLineTo(event->pos()); + scribbling = false; + /*emit*/ emitSelection(); + } +} + +bool DrawingPlane::eventFilter(QObject* o, QEvent* e) +{ + if (o == glView) { + if (e->type() == QEvent::Resize) + resizeEvent(static_cast(e)); + else if (e->type() == QEvent::MouseButtonPress) + mousePressEvent(static_cast(e)); + else if (e->type() == QEvent::MouseButtonRelease) + mouseReleaseEvent(static_cast(e)); + else if (e->type() == QEvent::MouseMove) + mouseMoveEvent(static_cast(e)); + } + + return false; +} + +void DrawingPlane::resizeEvent(QResizeEvent *event) +{ + QImage img(event->size(), QImage::Format_ARGB32); + img.fill(qRgba(255, 255, 255, 0)); + image = img; +} + +void DrawingPlane::drawLineTo(const QPoint &endPoint) +{ + QPainter painter(&image); + painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap, + Qt::RoundJoin)); + painter.setOpacity(0.5); + painter.drawLine(lastPoint.x(), image.height()-lastPoint.y(), endPoint.x(), image.height()-endPoint.y()); + + QImage img = image;//QGLWidget::convertToGLFormat(image); + int nc = img.numBytes() / ( img.width() * img.height() ); + data.setValue(SbVec2s(img.width(), img.height()), nc, img.bits()); + soqt->scheduleRedraw(); + lastPoint = endPoint; +} + +// ------------------------------------------------- RemoveComponentsDialog::RemoveComponentsDialog(QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl) diff --git a/src/Mod/Mesh/Gui/RemoveComponents.h b/src/Mod/Mesh/Gui/RemoveComponents.h index 1ae66850d8..96f25a1314 100644 --- a/src/Mod/Mesh/Gui/RemoveComponents.h +++ b/src/Mod/Mesh/Gui/RemoveComponents.h @@ -25,12 +25,14 @@ #define MESHGUI_REMOVECOMPONENTS_H #include -#include #include #include +#include "MeshSelection.h" // forward declarations -class SoEventCallback; +class SoNode; +class SoQtViewer; +class SoSFImage; namespace App { class DocumentObject; } namespace Gui { class View3DInventorViewer; } namespace Gui { class Document; } @@ -40,6 +42,42 @@ namespace MeshGui { class ViewProviderMesh; class Ui_RemoveComponents; +class DrawingPlane : public QObject +{ + Q_OBJECT + +public: + DrawingPlane(SoSFImage&, SoQtViewer*, QWidget* view); + virtual ~DrawingPlane(); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void resizeEvent(QResizeEvent *event); + bool eventFilter(QObject* o, QEvent* e); + +protected Q_SLOTS: + void changeRadius(double); + +Q_SIGNALS: + void emitSelection(); + +private: + void drawLineTo(const QPoint &endPoint); + + bool scribbling; + int myPenWidth; + float myRadius; + QColor myPenColor; + QPoint lastPoint; + QList selection; + QImage image; + SoSFImage& data; + SoQtViewer* soqt; + QWidget* glView; +}; + /** * Non-modal dialog to de/select components, regions, the complete or single faces * of a mesh and delete them. @@ -65,23 +103,18 @@ public Q_SLOTS: void on_deselectAll_clicked(); void on_deselectComponents_clicked(); void on_deselectTriangle_clicked(); + void on_visibleTriangles_toggled(bool); + void on_screenTriangles_toggled(bool); + void on_cbSelectComp_toggled(bool); + void on_cbDeselectComp_toggled(bool); protected: void changeEvent(QEvent *e); - -private: - std::list getViewProviders(const Gui::Document*) const; - Gui::View3DInventorViewer* getViewer() const; - void startInteractiveCallback(Gui::View3DInventorViewer* ,SoEventCallbackCB *); - void stopInteractiveCallback(Gui::View3DInventorViewer*); - - static void selectGLCallback(void * ud, SoEventCallback * n); - static void pickFaceCallback(void * ud, SoEventCallback * n); + void paintSelection(); private: Ui_RemoveComponents* ui; - SoEventCallbackCB *_interactiveMode; - bool selectRegion; + MeshSelection meshSel; }; /** diff --git a/src/Mod/Mesh/Gui/RemoveComponents.ui b/src/Mod/Mesh/Gui/RemoveComponents.ui index 7fb4401b22..04dc1d1790 100644 --- a/src/Mod/Mesh/Gui/RemoveComponents.ui +++ b/src/Mod/Mesh/Gui/RemoveComponents.ui @@ -193,12 +193,12 @@ - + Respect only visible triangles - true + false @@ -207,6 +207,9 @@ Respect only triangles with normals facing screen + + true + diff --git a/src/Mod/Mesh/Gui/Selection.cpp b/src/Mod/Mesh/Gui/Selection.cpp new file mode 100644 index 0000000000..ae6e1aeaf2 --- /dev/null +++ b/src/Mod/Mesh/Gui/Selection.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "Selection.h" +#include "ui_Selection.h" + +using namespace MeshGui; + + +/* TRANSLATOR MeshGui::Selection */ + +Selection::Selection(QWidget* parent) + : QWidget(parent), ui(new Ui_Selection()) +{ + ui->setupUi(this); + ui->addSelection->installEventFilter(this); + ui->clearSelection->installEventFilter(this); + + meshSel.setCheckOnlyVisibleTriangles(ui->visibleTriangles->isChecked()); + meshSel.setCheckOnlyPointToUserTriangles(ui->screenTriangles->isChecked()); +} + +/* + * Destroys the object and frees any allocated resources + */ +Selection::~Selection() +{ + // no need to delete child widgets, Qt does it all for us + delete ui; + meshSel.clearSelection(); +} + +void Selection::setObjects(const std::vector& o) +{ + meshSel.setObjects(o); +} + +std::vector Selection::getObjects() const +{ + return meshSel.getObjects(); +} + +bool Selection::eventFilter(QObject* o, QEvent* e) +{ + if (e->type() == QEvent::HoverEnter) { + if (o == ui->addSelection) { + ui->label->setText(tr("Use a brush tool to select the area")); + } + else if (o == ui->clearSelection) { + ui->label->setText(tr("Clears completely the selected area")); + } + } + else if (e->type() == QEvent::HoverLeave) { + if (o == ui->addSelection) { + ui->label->clear(); + } + else if (o == ui->clearSelection) { + ui->label->clear(); + } + } + + return false; +} + +void Selection::on_addSelection_clicked() +{ + meshSel.startSelection(); +} + +void Selection::on_clearSelection_clicked() +{ + meshSel.clearSelection(); +} + +void Selection::on_visibleTriangles_toggled(bool on) +{ + meshSel.setCheckOnlyVisibleTriangles(on); +} + +void Selection::on_screenTriangles_toggled(bool on) +{ + meshSel.setCheckOnlyPointToUserTriangles(on); +} + +#include "moc_Selection.cpp" diff --git a/src/Mod/Mesh/Gui/Selection.h b/src/Mod/Mesh/Gui/Selection.h new file mode 100644 index 0000000000..bb6952a50a --- /dev/null +++ b/src/Mod/Mesh/Gui/Selection.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_SELECTION_H +#define MESHGUI_SELECTION_H + +#include +#include +#include +#include +#include +#include +#include "MeshSelection.h" + +namespace MeshGui { + +class Ui_Selection; +class Selection : public QWidget +{ + Q_OBJECT + +public: + Selection(QWidget* parent = 0); + ~Selection(); + void setObjects(const std::vector&); + std::vector getObjects() const; + bool eventFilter(QObject*, QEvent*); + +private Q_SLOTS: + void on_addSelection_clicked(); + void on_clearSelection_clicked(); + void on_visibleTriangles_toggled(bool); + void on_screenTriangles_toggled(bool); + +private: + MeshSelection meshSel; + Ui_Selection* ui; +}; + +} + +#endif // MESHGUI_SELECTION_H diff --git a/src/Mod/Mesh/Gui/Selection.ui b/src/Mod/Mesh/Gui/Selection.ui new file mode 100644 index 0000000000..db50a26434 --- /dev/null +++ b/src/Mod/Mesh/Gui/Selection.ui @@ -0,0 +1,71 @@ + + + MeshGui::Selection + + + + 0 + 0 + 304 + 143 + + + + Selection + + + + + + Selection + + + + + + Add + + + + + + + Clear + + + + + + + Respect only visible triangles + + + false + + + + + + + Respect only triangles with normals facing screen + + + true + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Mesh/Gui/SoPolygon.cpp b/src/Mod/Mesh/Gui/SoPolygon.cpp new file mode 100644 index 0000000000..66818d8985 --- /dev/null +++ b/src/Mod/Mesh/Gui/SoPolygon.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (c) 2008 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# ifdef FC_OS_WIN32 +# include +# endif +# ifdef FC_OS_MACOSX +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +# include +# include + +#include "SoPolygon.h" + +using namespace MeshGui; + + +SO_NODE_SOURCE(SoPolygon); + +void SoPolygon::initClass() +{ + SO_NODE_INIT_CLASS(SoPolygon, SoShape, "Shape"); +} + +SoPolygon::SoPolygon() +{ + SO_NODE_CONSTRUCTOR(SoPolygon); + + SO_NODE_ADD_FIELD(startIndex, (0)); + SO_NODE_ADD_FIELD(numVertices, (0)); + SO_NODE_ADD_FIELD(highlight, (FALSE)); + SO_NODE_ADD_FIELD(render, (TRUE)); +} + +/** + * Renders the polygon. + */ +void SoPolygon::GLRender(SoGLRenderAction *action) +{ + if (shouldGLRender(action) && render.getValue()) + { + SoState* state = action->getState(); + const SoCoordinateElement * coords = SoCoordinateElement::getInstance(state); + if (!coords) return; + const SbVec3f * points = coords->getArrayPtr3(); + if (!points) return; + + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); + mb.sendFirst(); // make sure we have the correct material + + int32_t len = coords->getNum(); + drawPolygon(points, len); + } +} + +/** + * Renders the polygon. + */ +void SoPolygon::drawPolygon(const SbVec3f * points,int32_t len) const +{ + glLineWidth(3.0f); + int32_t beg = startIndex.getValue(); + int32_t cnt = numVertices.getValue(); + int32_t end = beg + cnt; + if (end > len) + return; // wrong setup, too few points + // draw control mesh + glBegin(GL_LINES); + for (int32_t i = beg; i < end; ++i) { + int32_t j = (i-beg+1) % cnt + beg; + glVertex3fv(points[i].getValue()); + glVertex3fv(points[j].getValue()); + } + glEnd(); +} + +/** + * Calculates picked point based on primitives generated by subclasses. + */ +void +SoPolygon::rayPick(SoRayPickAction * action) +{ + //if (this->shouldRayPick(action)) { + // this->computeObjectSpaceRay(action); + + // const SoBoundingBoxCache* bboxcache = getBoundingBoxCache(); + // if (!bboxcache || !bboxcache->isValid(action->getState()) || + // SoFCMeshObjectShape_ray_intersect(action, bboxcache->getProjectedBox())) { + // this->generatePrimitives(action); + // } + //} + inherited::rayPick(action); +} + +void SoPolygon::generatePrimitives(SoAction* action) +{ +} + +/** + * Sets the bounding box of the mesh to \a box and its center to \a center. + */ +void SoPolygon::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) +{ + SoState* state = action->getState(); + const SoCoordinateElement * coords = SoCoordinateElement::getInstance(state); + if (!coords) return; + const SbVec3f * points = coords->getArrayPtr3(); + if (!points) return; + float maxX=-FLT_MAX, minX=FLT_MAX, + maxY=-FLT_MAX, minY=FLT_MAX, + maxZ=-FLT_MAX, minZ=FLT_MAX; + int32_t len = coords->getNum(); + int32_t beg = startIndex.getValue(); + int32_t cnt = numVertices.getValue(); + int32_t end = beg + cnt; + if (end <= len) { + for (int32_t i=beg; i(maxX,points[i][0]); + minX = std::min(minX,points[i][0]); + maxY = std::max(maxY,points[i][1]); + minY = std::min(minY,points[i][1]); + maxZ = std::max(maxZ,points[i][2]); + minZ = std::min(minZ,points[i][2]); + } + + box.setBounds(minX,minY,minZ,maxX,maxY,maxZ); + center.setValue(0.5f*(minX+maxX),0.5f*(minY+maxY),0.5f*(minZ+maxZ)); + } + else { + box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0)); + center.setValue(0.0f,0.0f,0.0f); + } +} diff --git a/src/Mod/Mesh/Gui/SoPolygon.h b/src/Mod/Mesh/Gui/SoPolygon.h new file mode 100644 index 0000000000..3df9d3a27d --- /dev/null +++ b/src/Mod/Mesh/Gui/SoPolygon.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (c) 2008 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef MESHGUI_SOPOLYGON_H +#define MESHGUI_SOPOLYGON_H + +#include +#include +#include +#include +#include +#include +#include + +namespace MeshGui { + +class MeshGuiExport SoPolygon : public SoShape { + typedef SoShape inherited; + + SO_NODE_HEADER(SoPolygon); + +public: + static void initClass(); + SoPolygon(); + + SoSFInt32 startIndex; + SoSFInt32 numVertices; + SoSFBool highlight; + SoSFBool render; + +protected: + virtual ~SoPolygon() {}; + virtual void GLRender(SoGLRenderAction *action); + virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er); + virtual void rayPick (SoRayPickAction *action); + virtual void generatePrimitives(SoAction *action); + +private: + void drawPolygon(const SbVec3f *,int32_t) const; +}; + +} // namespace MeshGui + + +#endif // MESHGUI_SOPOLYGON_H + diff --git a/src/Mod/Mesh/Gui/ViewProvider.cpp b/src/Mod/Mesh/Gui/ViewProvider.cpp index 196857b06d..3682f76e01 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.cpp +++ b/src/Mod/Mesh/Gui/ViewProvider.cpp @@ -1069,8 +1069,14 @@ std::vector ViewProviderMesh::getVisibleFacets(const SbViewportRe } mat->diffuseColor.finishEditing(); + + // backface culling + //SoShapeHints* hints = new SoShapeHints; + //hints->shapeType = SoShapeHints::SOLID; + //hints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; SoMaterialBinding* bind = new SoMaterialBinding(); bind->value = SoMaterialBinding::PER_FACE; + //root->addChild(hints); root->addChild(mat); root->addChild(bind); #endif @@ -1514,12 +1520,17 @@ void ViewProviderMesh::deselectFacet(unsigned long facet) pcMatBinding->value = SoMaterialBinding::PER_FACE; int uCtFacets = (int)rMesh.countFacets(); - if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) { - highlightSelection(); + if (rMesh.hasSelectedFacets()) { + if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) { + highlightSelection(); + } + else { + App::Color c = ShapeColor.getValue(); + pcShapeMaterial->diffuseColor.set1Value(facet,c.r,c.g,c.b); + } } else { - App::Color c = ShapeColor.getValue(); - pcShapeMaterial->diffuseColor.set1Value(facet,c.r,c.g,c.b); + unhighlightSelection(); } } @@ -1552,7 +1563,10 @@ void ViewProviderMesh::deselectComponent(unsigned long uFacet) rMesh.removeFacetsFromSelection(selection); // Colorize the selection - highlightSelection(); + if (rMesh.hasSelectedFacets()) + highlightSelection(); + else + unhighlightSelection(); } void ViewProviderMesh::setSelection(const std::vector& indices) @@ -1583,7 +1597,10 @@ void ViewProviderMesh::removeSelection(const std::vector& indices rMesh.removeFacetsFromSelection(indices); // Colorize the selection - highlightSelection(); + if (rMesh.hasSelectedFacets()) + highlightSelection(); + else + unhighlightSelection(); } void ViewProviderMesh::clearSelection() @@ -1600,6 +1617,7 @@ void ViewProviderMesh::deleteSelection() const Mesh::MeshObject& rMesh = meshProp.getValue(); rMesh.getFacetsFromSelection(indices); if (!indices.empty()) { + rMesh.clearFacetSelection(); unhighlightSelection(); Mesh::MeshObject* pMesh = meshProp.startEditing(); From ef1a3312f11631226cfb0d1fc3f332236b57aad8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Apr 2013 19:24:39 +0200 Subject: [PATCH 44/53] Add a GLPainter class to do all the OpenGL drawing stuff --- src/Gui/CMakeLists.txt | 2 + src/Gui/Flag.cpp | 55 ++---- src/Gui/Flag.h | 4 +- src/Gui/GLPainter.cpp | 184 ++++++++++++++++++++ src/Gui/GLPainter.h | 77 ++++++++ src/Gui/MouseSelection.cpp | 52 ++++-- src/Gui/Thumbnail.cpp | 13 ++ src/Gui/View3DInventorViewer.cpp | 177 +------------------ src/Gui/View3DInventorViewer.h | 10 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 16 +- 10 files changed, 346 insertions(+), 244 deletions(-) create mode 100644 src/Gui/GLPainter.cpp create mode 100644 src/Gui/GLPainter.h diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 9c3d1641a1..43fa94ed7a 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -576,6 +576,7 @@ SOURCE_GROUP("Widget\\iisTaskPanel\\Mocs" FILES ${iis_MOC_SRCS}) # The 3d view SET(View3D_CPP_SRCS Flag.cpp + GLPainter.cpp MouseSelection.cpp NavigationStyle.cpp InventorNavigationStyle.cpp @@ -592,6 +593,7 @@ SET(View3D_CPP_SRCS SET(View3D_SRCS ${View3D_CPP_SRCS} Flag.h + GLPainter.h MouseSelection.h NavigationStyle.h SplitView3DInventor.h diff --git a/src/Gui/Flag.cpp b/src/Gui/Flag.cpp index bf8e4e500b..7ae9c269a3 100644 --- a/src/Gui/Flag.cpp +++ b/src/Gui/Flag.cpp @@ -27,6 +27,8 @@ # include #endif #include +#include "View3DInventorViewer.h" +#include "GLPainter.h" #include "Flag.h" @@ -192,7 +194,7 @@ const SbVec3f& Flag::getOrigin() const return this->coord; } -void Flag::drawLine (int tox, int toy) +void Flag::drawLine (View3DInventorViewer* v, int tox, int toy) { if (!isVisible()) return; @@ -204,50 +206,17 @@ void Flag::drawLine (int tox, int toy) int fromy = pos().y() + height()/2; if (false) fromx += width(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, view[0], 0, view[1], -1, 1); - - // Store GL state - glPushAttrib(GL_ALL_ATTRIB_BITS); - GLfloat depthrange[2]; - glGetFloatv(GL_DEPTH_RANGE, depthrange); - GLdouble projectionmatrix[16]; - glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); - - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); - glDepthRange(0,0); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_BLEND); - - glColor4f(1.0, 1.0, 1.0, 0.0); - glViewport(0, 0, view[0], view[1]); + GLPainter p; + p.begin(v); + p.setDrawBuffer(GL_BACK); // the line - glLineWidth(1.0f); - glBegin(GL_LINE_LOOP); - glVertex3i(fromx, view[1]-fromy, 0); - glVertex3i(tox , view[1]-toy , 0); - glEnd(); - - glPointSize(3.0f); - glBegin(GL_POINTS); - glVertex3i(tox , view[1]-toy , 0); - glEnd(); - - glFlush(); - - // Reset original state - glDepthRange(depthrange[0], depthrange[1]); - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(projectionmatrix); - - glPopAttrib(); - glPopMatrix(); + p.setLineWidth(1.0f); + p.drawLine(fromx, fromy, tox, toy); + // the point + p.setPointSize(3.0f); + p.drawPoint(tox, toy); + p.end(); } void Flag::setText(const QString& t) diff --git a/src/Gui/Flag.h b/src/Gui/Flag.h index 2c6d7b05e2..36d196a05c 100644 --- a/src/Gui/Flag.h +++ b/src/Gui/Flag.h @@ -31,7 +31,7 @@ #include namespace Gui { - +class View3DInventorViewer; /** * @author Werner Mayer */ @@ -47,7 +47,7 @@ public: QSize sizeHint() const; void setOrigin(const SbVec3f&); const SbVec3f& getOrigin() const; - void drawLine(int tox, int toy); + void drawLine(Gui::View3DInventorViewer*, int tox, int toy); void setText(const QString&); protected: diff --git a/src/Gui/GLPainter.cpp b/src/Gui/GLPainter.cpp new file mode 100644 index 0000000000..81bffea6c4 --- /dev/null +++ b/src/Gui/GLPainter.cpp @@ -0,0 +1,184 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "GLPainter.h" +#include "View3DInventorViewer.h" + +using namespace Gui; + +GLPainter::GLPainter() : viewer(0), logicOp(false), lineStipple(false) +{ +} + +GLPainter::~GLPainter() +{ + end(); +} + +bool GLPainter::begin(View3DInventorViewer* v) +{ + if (viewer) + return false; + viewer = v; + + // Make current context + SbVec2s view = viewer->getGLSize(); + this->width = view[0]; + this->height = view[1]; + + viewer->glLockNormal(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, this->width, 0, this->height, -1, 1); + + // Store GL state + glPushAttrib(GL_ALL_ATTRIB_BITS); + glGetFloatv(GL_DEPTH_RANGE, this->depthrange); + glGetDoublev(GL_PROJECTION_MATRIX, this->projectionmatrix); + + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); + glDepthRange(0,0); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_BLEND); + + glLineWidth(1.0f); + glColor4f(1.0, 1.0, 1.0, 0.0); + glViewport(0, 0, this->width, this->height); + glDrawBuffer(GL_FRONT); + + return true; +} + +bool GLPainter::end() +{ + if (!viewer) + return false; + + glFlush(); + if (this->logicOp) { + this->logicOp = false; + glDisable(GL_COLOR_LOGIC_OP); + } + if (this->lineStipple) { + this->lineStipple = false; + glDisable(GL_LINE_STIPPLE); + } + + // Reset original state + glDepthRange(this->depthrange[0], this->depthrange[1]); + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(this->projectionmatrix); + + glPopAttrib(); + glPopMatrix(); + + // Release the context + viewer->glUnlockNormal(); + + viewer = 0; + return true; +} + +bool GLPainter::isActive() const +{ + return viewer != 0; +} + +void GLPainter::setLineWidth(float w) +{ + glLineWidth(w); +} + +void GLPainter::setPointSize(float s) +{ + glPointSize(s); +} + +void GLPainter::setColor(float r, float g, float b, float a) +{ + glColor4f(r, g, b, a); +} + +void GLPainter::setLogicOp(GLenum mode) +{ + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(mode); + this->logicOp = true; +} + +void GLPainter::setDrawBuffer(GLenum mode) +{ + glDrawBuffer(mode); +} + +void GLPainter::setLineStipple(GLint factor, GLushort pattern) +{ + glEnable(GL_LINE_STIPPLE); + glLineStipple(factor, pattern); + this->lineStipple = true; +} + +// Draw routines +void GLPainter::drawRect(int x1, int y1, int x2, int y2) +{ + if (!viewer) + return; + + glBegin(GL_LINE_LOOP); + glVertex3i(x1, this->height-y1, 0); + glVertex3i(x2, this->height-y1, 0); + glVertex3i(x2, this->height-y2, 0); + glVertex3i(x1, this->height-y2, 0); + glEnd(); +} + +void GLPainter::drawLine (int x1, int y1, int x2, int y2) +{ + if (!viewer) + return; + + glBegin(GL_LINES); + glVertex3i(x1, this->height-y1, 0); + glVertex3i(x2, this->height-y2, 0); + glEnd(); +} + +void GLPainter::drawPoint(int x, int y) +{ + if (!viewer) + return; + + glBegin(GL_POINTS); + glVertex3i(x, this->height-y, 0); + glEnd(); +} diff --git a/src/Gui/GLPainter.h b/src/Gui/GLPainter.h new file mode 100644 index 0000000000..170ce63578 --- /dev/null +++ b/src/Gui/GLPainter.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2013 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_GLPAINTER_H +#define GUI_GLPAINTER_H + +#ifdef FC_OS_WIN32 +#include +#endif +#ifdef FC_OS_MACOSX +#include +#else +#include +#endif + +namespace Gui { +class View3DInventorViewer; +class GuiExport GLPainter +{ +public: + GLPainter(); + virtual ~GLPainter(); + + bool begin(View3DInventorViewer*); + bool end(); + bool isActive() const; + + /** @name Setter methods */ + //@{ + void setLineWidth(float); + void setPointSize(float); + void setColor(float, float, float, float=0); + void setLogicOp(GLenum); + void setDrawBuffer(GLenum); + void setLineStipple(GLint factor, GLushort pattern); + //@} + + /** @name Draw routines */ + //@{ + void drawRect (int x, int y, int w, int h); + void drawLine (int x1, int y1, int x2, int y2); + void drawPoint(int x, int y); + //@} + +private: + View3DInventorViewer* viewer; + GLfloat depthrange[2]; + GLdouble projectionmatrix[16]; + GLint width, height; + bool logicOp; + bool lineStipple; +}; + +} // namespace Gui + +#endif // GUI_GLPAINTER_H + diff --git a/src/Gui/MouseSelection.cpp b/src/Gui/MouseSelection.cpp index e5b92b0796..dccf871427 100644 --- a/src/Gui/MouseSelection.cpp +++ b/src/Gui/MouseSelection.cpp @@ -41,6 +41,7 @@ #include "MouseSelection.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" +#include "GLPainter.h" using namespace Gui; @@ -263,10 +264,15 @@ void PolyPickerSelection::draw () if (mustRedraw){ if (_cNodeVector.size() > 1) { QPoint start = _cNodeVector.front(); + GLPainter p; + p.begin(_pcView3D); + p.setColor(1.0f,1.0f,1.0f); + p.setLogicOp(GL_XOR); for (std::vector::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) { - _pcView3D->drawLine(start.x(),start.y(),it->x(), it->y() ); + p.drawLine(start.x(),start.y(),it->x(), it->y()); start = *it; } + p.end(); } // recursive call, but no infinite loop @@ -279,15 +285,25 @@ void PolyPickerSelection::draw () if (_cNodeVector.size() > 2) { QPoint start = _cNodeVector.front(); - _pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y() ); + GLPainter p; + p.begin(_pcView3D); + p.setColor(1.0f,1.0f,1.0f); + p.setLogicOp(GL_XOR); + p.drawLine(m_iXnew,m_iYnew,start.x(), start.y()); + p.end(); } } else { - _pcView3D->drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold); + GLPainter p; + p.begin(_pcView3D); + p.setColor(1.0f,1.0f,1.0f); + p.setLogicOp(GL_XOR); + p.drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold); if (_cNodeVector.size() > 1) { QPoint start = _cNodeVector.front(); - _pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y()); + p.drawLine(m_iXnew,m_iYnew,start.x(), start.y()); } + p.end(); } } } @@ -494,11 +510,15 @@ void BrushSelection::draw () if (mustRedraw){ if (_cNodeVector.size() > 1) { QPoint start = _cNodeVector.front(); + GLPainter p; + p.begin(_pcView3D); + p.setLineWidth(this->l); + p.setColor(this->r, this->g, this->b, this->a); for (std::vector::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) { - _pcView3D->drawLine(start.x(),start.y(),it->x(), it->y(), - this->l, this->r, this->g, this->b, this->a); + p.drawLine(start.x(),start.y(),it->x(), it->y()); start = *it; } + p.end(); } // recursive call, but no infinite loop @@ -506,8 +526,12 @@ void BrushSelection::draw () draw(); } if (m_bWorking) { - _pcView3D->drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold, - this->l, this->r, this->g, this->b, this->a); + GLPainter p; + p.begin(_pcView3D); + p.setLineWidth(this->l); + p.setColor(this->r, this->g, this->b, this->a); + p.drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold); + p.end(); } } @@ -664,8 +688,16 @@ void RectangleSelection::terminate() void RectangleSelection::draw () { - if (m_bWorking) - _pcView3D->drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew); + if (m_bWorking) { + GLPainter p; + p.begin(_pcView3D); + p.setColor(1.0, 1.0, 0.0, 0.0); + p.setLogicOp(GL_XOR); + p.setLineWidth(3.0f); + p.setLineStipple(2, 0x3F3F); + p.drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew); + p.end(); + } } int RectangleSelection::mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos ) diff --git a/src/Gui/Thumbnail.cpp b/src/Gui/Thumbnail.cpp index df5cbdf3a0..aeb0a594a2 100644 --- a/src/Gui/Thumbnail.cpp +++ b/src/Gui/Thumbnail.cpp @@ -87,6 +87,19 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const QImage img; try { this->viewer->savePicture(this->size, this->size, View3DInventorViewer::Current, img); + // Alternative way of off-screen rendering +#if 0 + QGLFramebufferObject fbo(this->size, this->size,QGLFramebufferObject::Depth); + fbo.bind(); + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDepthRange(0.1,1.0); + glEnable(GL_LINE_SMOOTH); + SoGLRenderAction gl(SbViewportRegion(this->size,this->size)); + gl.apply(this->viewer->getSceneManager()->getSceneGraph()); + fbo.release(); + img = fbo.toImage(); +#endif } catch (...) { return; // offscreen rendering failed diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 5843f4bea3..2d9328c26d 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -948,7 +948,7 @@ void View3DInventorViewer::actualRedraw(void) vv.projectToScreen(pt, pt); int tox = (int)(pt[0] * size[0]); int toy = (int)((1.0f-pt[1]) * size[1]); - flag->drawLine(tox, toy); + flag->drawLine(this, tox, toy); } } } @@ -1506,181 +1506,6 @@ void View3DInventorViewer::viewSelection() root->unref(); } -// Draw routines -void View3DInventorViewer::drawRect(int x1, int y1, int x2, int y2) -{ - // Make current context - SbVec2s view = this->getGLSize(); - this->glLockNormal(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, view[0], 0, view[1], -1, 1); - - // Store GL state - glPushAttrib(GL_ALL_ATTRIB_BITS); - GLfloat depthrange[2]; - glGetFloatv(GL_DEPTH_RANGE, depthrange); - GLdouble projectionmatrix[16]; - glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); - - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); - glDepthRange(0,0); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_BLEND); - - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_XOR); - glDrawBuffer(GL_FRONT); - glLineWidth(3.0f); - glEnable(GL_LINE_STIPPLE); - glLineStipple(2, 0x3F3F); - glColor4f(1.0, 1.0, 0.0, 0.0); - glViewport(0, 0, view[0], view[1]); - - glBegin(GL_LINE_LOOP); - glVertex3i(x1, view[1]-y1, 0); - glVertex3i(x2, view[1]-y1, 0); - glVertex3i(x2, view[1]-y2, 0); - glVertex3i(x1, view[1]-y2, 0); - glEnd(); - - glFlush(); - glDisable(GL_LINE_STIPPLE); - glDisable(GL_COLOR_LOGIC_OP); - - // Reset original state - glDepthRange(depthrange[0], depthrange[1]); - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(projectionmatrix); - - glPopAttrib(); - glPopMatrix(); - - // Release the context - this->glUnlockNormal(); -} - -void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2) -{ - // Make current context - SbVec2s view = this->getGLSize(); - this->glLockNormal(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, view[0], 0, view[1], -1, 1); - - // Store GL state - glPushAttrib(GL_ALL_ATTRIB_BITS); - GLfloat depthrange[2]; - glGetFloatv(GL_DEPTH_RANGE, depthrange); - GLdouble projectionmatrix[16]; - glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); - - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); - glDepthRange(0,0); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_BLEND); - - glLineWidth(1.0f); - glColor4f(1.0, 1.0, 1.0, 0.0); - glViewport(0, 0, view[0], view[1]); - - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_XOR); - glDrawBuffer(GL_FRONT); - - glBegin(GL_LINES); - glVertex3i(x1, view[1]-y1, 0); - glVertex3i(x2, view[1]-y2, 0); - glEnd(); - - glFlush(); - glLogicOp(GL_COPY); - glDisable(GL_COLOR_LOGIC_OP); - - // Reset original state - glDepthRange(depthrange[0], depthrange[1]); - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(projectionmatrix); - - glPopAttrib(); - glPopMatrix(); - - // Release the context - this->glUnlockNormal(); -} - -void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2, GLfloat line, - GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha, - GLenum op) -{ - // Make current context - SbVec2s view = this->getGLSize(); - this->glLockNormal(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, view[0], 0, view[1], -1, 1); - - // Store GL state - glPushAttrib(GL_ALL_ATTRIB_BITS); - GLfloat depthrange[2]; - glGetFloatv(GL_DEPTH_RANGE, depthrange); - GLdouble projectionmatrix[16]; - glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); - - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); - glDepthRange(0,0); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_BLEND); - - glLineWidth(line); - glColor4f(red, green, blue, alpha); - glViewport(0, 0, view[0], view[1]); - - if (op > 0) { - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(op); - } - glDrawBuffer(GL_FRONT); - - glBegin(GL_LINES); - glVertex3i(x1, view[1]-y1, 0); - glVertex3i(x2, view[1]-y2, 0); - glEnd(); - - glFlush(); - if (op) { - glLogicOp(GL_COPY); - glDisable(GL_COLOR_LOGIC_OP); - } - - // Reset original state - glDepthRange(depthrange[0], depthrange[1]); - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(projectionmatrix); - - glPopAttrib(); - glPopMatrix(); - - // Release the context - this->glUnlockNormal(); -} - /*! Decide if it should be possible to start a spin animation of the model in the viewer by releasing the mouse button while dragging. diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 88985f8462..c53298a1f3 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -252,15 +252,6 @@ public: */ void viewSelection(); - /** @name Draw routines */ - //@{ - void drawRect (int x, int y, int w, int h); - void drawLine (int x1, int y1, int x2, int y2); - void drawLine (int x1, int y1, int x2, int y2, - GLfloat line, GLfloat red, GLfloat green, - GLfloat blue, GLfloat alpha, GLenum op=0); - //@} - void setGradientBackgroud(bool b); void setGradientBackgroudColor(const SbColor& fromColor, const SbColor& toColor); @@ -331,6 +322,7 @@ private: // friends friend class NavigationStyle; + friend class GLPainter; }; } // namespace Gui diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 57e6c6ba62..88b1193a2b 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -931,10 +932,17 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor case STATUS_SKETCH_UseRubberBand: { // a redraw is required in order to clear any previous rubberband draw(true); - viewer->drawRect(prvCursorPos.getValue()[0], - viewer->getGLWidget()->height() - prvCursorPos.getValue()[1], - cursorPos.getValue()[0], - viewer->getGLWidget()->height() - cursorPos.getValue()[1]); + Gui::GLPainter p; + p.begin(viewer); + p.setColor(1.0, 1.0, 0.0, 0.0); + p.setLogicOp(GL_XOR); + p.setLineWidth(3.0f); + p.setLineStipple(2, 0x3F3F); + p.drawRect(prvCursorPos.getValue()[0], + viewer->getGLWidget()->height() - prvCursorPos.getValue()[1], + cursorPos.getValue()[0], + viewer->getGLWidget()->height() - cursorPos.getValue()[1]); + p.end(); return true; } default: From af8955aac036d3865a587dbd0d0efb3a6cf1050a Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Apr 2013 20:45:16 +0200 Subject: [PATCH 45/53] Improve performance of box selection in sketcher --- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 15 +++++++++++---- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 88b1193a2b..636100a5fe 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -120,6 +120,7 @@ SbColor ViewProviderSketch::SelectColor (0.11f,0.68f,0.11f); // #1CAD SbTime ViewProviderSketch::prvClickTime; SbVec3f ViewProviderSketch::prvClickPoint; SbVec2s ViewProviderSketch::prvCursorPos; +SbVec2s ViewProviderSketch::newCursorPos; //************************************************************************** // Edit data structure @@ -457,6 +458,7 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe prvClickTime = SbTime::getTimeOfDay(); prvClickPoint = point; prvCursorPos = cursorPos; + newCursorPos = cursorPos; if (!done) Mode = STATUS_SKETCH_StartRubberBand; } @@ -930,18 +932,23 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor return true; } case STATUS_SKETCH_UseRubberBand: { - // a redraw is required in order to clear any previous rubberband - draw(true); Gui::GLPainter p; p.begin(viewer); p.setColor(1.0, 1.0, 0.0, 0.0); p.setLogicOp(GL_XOR); p.setLineWidth(3.0f); p.setLineStipple(2, 0x3F3F); + // first redraw the old rectangle with XOR to restore the correct colors p.drawRect(prvCursorPos.getValue()[0], viewer->getGLWidget()->height() - prvCursorPos.getValue()[1], - cursorPos.getValue()[0], - viewer->getGLWidget()->height() - cursorPos.getValue()[1]); + newCursorPos.getValue()[0], + viewer->getGLWidget()->height() - newCursorPos.getValue()[1]); + newCursorPos = cursorPos; + // now draw the new rectangle + p.drawRect(prvCursorPos.getValue()[0], + viewer->getGLWidget()->height() - prvCursorPos.getValue()[1], + newCursorPos.getValue()[0], + viewer->getGLWidget()->height() - newCursorPos.getValue()[1]); p.end(); return true; } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index e46d9febf1..e699dd269e 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -248,6 +248,7 @@ protected: static SbTime prvClickTime; static SbVec3f prvClickPoint; static SbVec2s prvCursorPos; + static SbVec2s newCursorPos; float zCross; float zLines; From 9505f0db99ac91d62c4f6ce22a770c0eb332c07c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Apr 2013 22:10:59 +0200 Subject: [PATCH 46/53] 0001087: Inventor Navigation continues with released Mouse Button --- src/Gui/CommandView.cpp | 8 +++++++- src/Gui/View3DInventorViewer.cpp | 2 +- src/Gui/View3DInventorViewer.h | 3 +++ src/Mod/Inspection/Gui/Command.cpp | 1 + src/Mod/Inspection/Gui/ViewProviderInspection.cpp | 1 + 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 9714ec0514..4b2d5b4102 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -1437,10 +1437,16 @@ void StdCmdToggleNavigation::activated(int iMsg) bool StdCmdToggleNavigation::isActive(void) { + //#0001087: Inventor Navigation continues with released Mouse Button + //This happens because 'Esc' is also used to close the task dialog. + //Add also new method 'isRedirectToSceneGraphEnabled' to explicitly + //check if this is allowed. + if (Gui::Control().activeDialog()) + return false; Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); - return viewer->isEditing(); + return viewer->isEditing() && viewer->isRedirectToSceneGraphEnabled(); } return false; } diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 2d9328c26d..f5dc4e8d38 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -138,7 +138,7 @@ SOQT_OBJECT_ABSTRACT_SOURCE(View3DInventorViewer); View3DInventorViewer::View3DInventorViewer (QWidget *parent, const char *name, SbBool embed, Type type, SbBool build) : inherited (parent, name, embed, type, build), editViewProvider(0),navigation(0), - editing(FALSE), redirected(FALSE) + editing(FALSE), redirected(FALSE), allowredir(FALSE) { Gui::Selection().Attach(this); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index c53298a1f3..072f2a0bda 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -182,6 +182,8 @@ public: void setEditingCursor (const QCursor& cursor); void setRedirectToSceneGraph(SbBool redirect) { this->redirected = redirect; } SbBool isRedirectedToSceneGraph() const { return this->redirected; } + void setRedirectToSceneGraphEnabled(SbBool enable) { this->allowredir = enable; } + SbBool isRedirectToSceneGraphEnabled(void) const { return this->allowredir; } //@} /** @name Pick actions */ @@ -311,6 +313,7 @@ private: SbBool editing; QCursor editCursor; SbBool redirected; + SbBool allowredir; void setCursorRepresentation(int mode); diff --git a/src/Mod/Inspection/Gui/Command.cpp b/src/Mod/Inspection/Gui/Command.cpp index 8176bdf407..75915160f7 100644 --- a/src/Mod/Inspection/Gui/Command.cpp +++ b/src/Mod/Inspection/Gui/Command.cpp @@ -87,6 +87,7 @@ void CmdInspectElement::activated(int iMsg) if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); + viewer->setRedirectToSceneGraphEnabled(true); viewer->setRedirectToSceneGraph(true); viewer->setEditingCursor(QCursor(Gui::BitmapFactory().pixmap("mesh_pipette"),4,29)); viewer->addEventCallback(SoButtonEvent::getClassTypeId(), diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp index dc6f246ed6..1783b63802 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp @@ -436,6 +436,7 @@ void ViewProviderInspection::inspectCallback(void * ud, SoEventCallback * n) view->setEditing(false); view->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); view->setRedirectToSceneGraph(false); + view->setRedirectToSceneGraphEnabled(false); view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback); } } From a19da3e4e3efb35dfc9bbbef414c83daac829f9b Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 28 Apr 2013 14:30:25 +0200 Subject: [PATCH 47/53] Fix possible crash in PropertyEnumeration class --- src/App/PropertyStandard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index f777c8d2ba..fb73ec4d0c 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -467,7 +467,7 @@ void PropertyEnumeration::setPyObject(PyObject *value) { if (PyInt_Check(value)) { long val = PyInt_AsLong(value); - if(_EnumArray){ + if (_EnumArray) { const char** plEnums = _EnumArray; long i=0; while(*(plEnums++) != NULL)i++; @@ -478,10 +478,10 @@ void PropertyEnumeration::setPyObject(PyObject *value) } else if (PyString_Check(value)) { const char* str = PyString_AsString (value); - if (isPartOf(str)) + if (_EnumArray && isPartOf(str)) setValue(PyString_AsString (value)); else - throw Py::ValueError("not a member of the enum"); + throw Py::ValueError("not part of the enum"); } else if (PyList_Check(value)) { Py_ssize_t nSize = PyList_Size(value); From 7b97150470024551e3584d18f551cd23b881e547 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 28 Apr 2013 14:31:12 +0200 Subject: [PATCH 48/53] Fix typo --- src/Gui/SplitView3DInventor.cpp | 6 +++--- src/Gui/View3DInventor.cpp | 6 +++--- src/Gui/View3DInventorViewer.cpp | 14 +++++++------- src/Gui/View3DInventorViewer.h | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index 102cb781e1..33879ffb27 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -204,7 +204,7 @@ void AbstractSplitView::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp } else if (strcmp(Reason,"Gradient") == 0) { for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) - (*it)->setGradientBackgroud((rGrp.GetBool("Gradient",true))); + (*it)->setGradientBackground((rGrp.GetBool("Gradient",true))); } else if (strcmp(Reason,"UseAntialiasing") == 0) { for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) @@ -238,9 +238,9 @@ void AbstractSplitView::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) { (*it)->setBackgroundColor(SbColor(r1, g1, b1)); if (rGrp.GetBool("UseBackgroundColorMid",false) == false) - (*it)->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3)); + (*it)->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3)); else - (*it)->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4)); + (*it)->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4)); } } } diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index e1a44f3d79..01e5fa1155 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -307,7 +307,7 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M _viewer->setAnimationEnabled(rGrp.GetBool("UseAutoRotation",true)); } else if (strcmp(Reason,"Gradient") == 0) { - _viewer->setGradientBackgroud((rGrp.GetBool("Gradient",true))); + _viewer->setGradientBackground((rGrp.GetBool("Gradient",true))); } else if (strcmp(Reason,"UseAntialiasing") == 0) { _viewer->getGLRenderAction()->setSmoothing(rGrp.GetBool("UseAntialiasing",false)); @@ -357,9 +357,9 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M r4 = ((col4 >> 24) & 0xff) / 255.0; g4 = ((col4 >> 16) & 0xff) / 255.0; b4 = ((col4 >> 8) & 0xff) / 255.0; _viewer->setBackgroundColor(SbColor(r1, g1, b1)); if (rGrp.GetBool("UseBackgroundColorMid",false) == false) - _viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3)); + _viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3)); else - _viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4)); + _viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4)); } } diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index f5dc4e8d38..c53e8b5665 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -258,7 +258,7 @@ View3DInventorViewer::View3DInventorViewer (QWidget *parent, const char *name, setViewing(false); setBackgroundColor(SbColor(0.1f, 0.1f, 0.1f)); - setGradientBackgroud(true); + setGradientBackground(true); // set some callback functions for user interaction addStartCallback(interactionStartCB); @@ -420,7 +420,7 @@ void View3DInventorViewer::handleEventCB(void * ud, SoEventCallback * n) SoGLWidgetElement::set(action->getState(), qobject_cast(that->getGLWidget())); } -void View3DInventorViewer::setGradientBackgroud(bool on) +void View3DInventorViewer::setGradientBackground(bool on) { if (on && backgroundroot->findChild(pcBackGround) == -1) backgroundroot->addChild(pcBackGround); @@ -428,15 +428,15 @@ void View3DInventorViewer::setGradientBackgroud(bool on) backgroundroot->removeChild(pcBackGround); } -void View3DInventorViewer::setGradientBackgroudColor(const SbColor& fromColor, - const SbColor& toColor) +void View3DInventorViewer::setGradientBackgroundColor(const SbColor& fromColor, + const SbColor& toColor) { pcBackGround->setColorGradient(fromColor, toColor); } -void View3DInventorViewer::setGradientBackgroudColor(const SbColor& fromColor, - const SbColor& toColor, - const SbColor& midColor) +void View3DInventorViewer::setGradientBackgroundColor(const SbColor& fromColor, + const SbColor& toColor, + const SbColor& midColor) { pcBackGround->setColorGradient(fromColor, toColor, midColor); } diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 072f2a0bda..8b2e295fb3 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -254,12 +254,12 @@ public: */ void viewSelection(); - void setGradientBackgroud(bool b); - void setGradientBackgroudColor(const SbColor& fromColor, - const SbColor& toColor); - void setGradientBackgroudColor(const SbColor& fromColor, - const SbColor& toColor, - const SbColor& midColor); + void setGradientBackground(bool b); + void setGradientBackgroundColor(const SbColor& fromColor, + const SbColor& toColor); + void setGradientBackgroundColor(const SbColor& fromColor, + const SbColor& toColor, + const SbColor& midColor); void setEnabledFPSCounter(bool b); void setNavigationType(Base::Type); NavigationStyle* navigationStyle() const; From 62474aa27b342275f12dcd9d8a4acfdc4eb2c25e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 28 Apr 2013 17:23:54 +0200 Subject: [PATCH 49/53] Switch new selection style explicitly off for some types --- src/Mod/Drawing/Gui/ViewProviderPage.h | 1 + src/Mod/Drawing/Gui/ViewProviderView.h | 1 + src/Mod/Mesh/Gui/ViewProvider.h | 1 + src/Mod/Mesh/Gui/ViewProviderCurvature.h | 1 + 4 files changed, 4 insertions(+) diff --git a/src/Mod/Drawing/Gui/ViewProviderPage.h b/src/Mod/Drawing/Gui/ViewProviderPage.h index 356ff65077..3504716527 100644 --- a/src/Mod/Drawing/Gui/ViewProviderPage.h +++ b/src/Mod/Drawing/Gui/ViewProviderPage.h @@ -53,6 +53,7 @@ public: virtual void attach(App::DocumentObject *); virtual void setDisplayMode(const char* ModeName); + virtual bool useNewSelectionModel(void) const {return false;} /// returns a list of all possible modes virtual std::vector getDisplayModes(void) const; diff --git a/src/Mod/Drawing/Gui/ViewProviderView.h b/src/Mod/Drawing/Gui/ViewProviderView.h index 0307f5845f..0969d88709 100644 --- a/src/Mod/Drawing/Gui/ViewProviderView.h +++ b/src/Mod/Drawing/Gui/ViewProviderView.h @@ -43,6 +43,7 @@ public: virtual void attach(App::DocumentObject *); virtual void setDisplayMode(const char* ModeName); + virtual bool useNewSelectionModel(void) const {return false;} /// returns a list of all possible modes virtual std::vector getDisplayModes(void) const; virtual void updateData(const App::Property*); diff --git a/src/Mod/Mesh/Gui/ViewProvider.h b/src/Mod/Mesh/Gui/ViewProvider.h index 3bf180bdd5..29b98065a4 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.h +++ b/src/Mod/Mesh/Gui/ViewProvider.h @@ -118,6 +118,7 @@ public: App::PropertyColor LineColor; virtual void attach(App::DocumentObject *); + virtual bool useNewSelectionModel(void) const {return false;} virtual QIcon getIcon() const; /// Sets the correct display mode virtual void setDisplayMode(const char* ModeName); diff --git a/src/Mod/Mesh/Gui/ViewProviderCurvature.h b/src/Mod/Mesh/Gui/ViewProviderCurvature.h index 9e58458db8..cb9edd4854 100644 --- a/src/Mod/Mesh/Gui/ViewProviderCurvature.h +++ b/src/Mod/Mesh/Gui/ViewProviderCurvature.h @@ -70,6 +70,7 @@ public: /// Extracts the mesh data from the feature \a pcFeature and creates an Inventor node \a SoNode with these data. void attach(App::DocumentObject* pcFeature); + virtual bool useNewSelectionModel(void) const {return false;} /// Sets the viewing mode void setDisplayMode(const char* ModeName); /// get the default display mode From 436386c005b2cf934e2d227902ab69dbde07cf36 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 28 Apr 2013 17:33:48 +0200 Subject: [PATCH 50/53] Fix typos --- src/Gui/DocumentPyImp.cpp | 3 +-- src/Gui/Tree.cpp | 14 +++++--------- src/Gui/Tree.h | 4 ++-- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Gui/DocumentPyImp.cpp b/src/Gui/DocumentPyImp.cpp index 535e58dd98..450fca8bda 100644 --- a/src/Gui/DocumentPyImp.cpp +++ b/src/Gui/DocumentPyImp.cpp @@ -270,7 +270,7 @@ PyObject* DocumentPy::toggleTreeItem(PyObject *args) Gui::ViewProviderDocumentObject* ActiveVp = dynamic_cast (getDocumentPtr()->getViewProvider(Object)) ; switch(mod) { case 0: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Toggle); break; - case 1: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Collaps); break; + case 1: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Collapse); break; case 2: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Expand); break; } } @@ -278,7 +278,6 @@ PyObject* DocumentPy::toggleTreeItem(PyObject *args) Py_Return; } - Py::Object DocumentPy::getActiveObject(void) const { App::DocumentObject *object = getDocumentPtr()->getDocument()->getActiveObject(); diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 67190c4fef..4faa227fd5 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -893,7 +893,6 @@ void DocumentItem::slotActiveObject(const Gui::ViewProviderDocumentObject& obj) void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& obj,const Gui::HighlightMode& high,bool set) { - std::string objectName = obj.getObject()->getNameInDocument(); std::map::iterator jt = ObjectMap.find(objectName); if (jt == ObjectMap.end()) @@ -915,27 +914,26 @@ void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& o // not defined enum assert(0); } + jt->second->setFont(0,f); - } void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj,const Gui::TreeItemMode& mode) { - std::string objectName = obj.getObject()->getNameInDocument(); std::map::iterator jt = ObjectMap.find(objectName); if (jt == ObjectMap.end()) return; // signal is emitted before the item gets created switch (mode) { - case Gui::Expand: + case Gui::Expand: jt->second->setExpanded(true); break; - case Gui::Collaps: + case Gui::Collapse: jt->second->setExpanded(false); break; - case Gui::Toggle: - if(jt->second->isExpanded()) + case Gui::Toggle: + if (jt->second->isExpanded()) jt->second->setExpanded(false); else jt->second->setExpanded(true); @@ -945,10 +943,8 @@ void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj, // not defined enum assert(0); } - } - const Gui::Document* DocumentItem::document() const { return this->pDocument; diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index 4e616daa59..be1126d6e0 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -49,8 +49,8 @@ enum HighlightMode { Underlined, /// highlight modes for the tree items enum TreeItemMode { Expand, - Collaps, - Toggle + Collapse, + Toggle }; From 63ddafd8e1775630ead70bc5b95d10772ac986b8 Mon Sep 17 00:00:00 2001 From: jriegel Date: Fri, 5 Apr 2013 15:44:29 +0200 Subject: [PATCH 51/53] Add active Analysis logic --- src/Mod/Fem/Gui/AppFemGuiPy.cpp | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/Mod/Fem/Gui/AppFemGuiPy.cpp b/src/Mod/Fem/Gui/AppFemGuiPy.cpp index d5ce3f616b..5b1a9c91aa 100755 --- a/src/Mod/Fem/Gui/AppFemGuiPy.cpp +++ b/src/Mod/Fem/Gui/AppFemGuiPy.cpp @@ -26,6 +26,71 @@ # include #endif +#include +#include +#include +#include +#include + +#include + + +// pointer to the active Analysis object +Fem::FemAnalysis *ActiveAnalysis =0; +Gui::Document *ActiveGuiDoc =0; +App::Document *ActiveAppDoc =0; +Gui::ViewProviderDocumentObject *ActiveVp =0; + + +/* module functions */ +static PyObject * setActiveAnalysis(PyObject *self, PyObject *args) +{ + if(ActiveAnalysis){ + // check if the document not already closed + std::vector docs = App::GetApplication().getDocuments(); + for(std::vector::const_iterator it=docs.begin();it!=docs.end();++it) + if(*it == ActiveAppDoc){ + ActiveGuiDoc->signalHighlightObject(*ActiveVp,Gui::Blue,false); + break; + } + + ActiveAnalysis = 0; + ActiveGuiDoc =0; + ActiveAppDoc =0; + ActiveVp =0; + } + + PyObject *object=0; + if (PyArg_ParseTuple(args,"|O!",&(App::DocumentObjectPy::Type), &object)&& object) { + App::DocumentObject* obj = static_cast(object)->getDocumentObjectPtr(); + if(!obj || !obj->getTypeId().isDerivedFrom(Fem::FemAnalysis::getClassTypeId()) ){ + PyErr_SetString(PyExc_Exception, "Active Analysis object have to be of type Fem::FemAnalysis!"); + return 0; + } + + // get the gui document of the Assembly Item + ActiveAnalysis = static_cast(obj); + ActiveAppDoc = ActiveAnalysis->getDocument(); + ActiveGuiDoc = Gui::Application::Instance->getDocument(ActiveAppDoc); + ActiveVp = dynamic_cast (ActiveGuiDoc->getViewProvider(ActiveAnalysis)) ; + ActiveGuiDoc->signalHighlightObject(*ActiveVp,Gui::Blue,true); + } + + Py_Return; +} + +/* module functions */ +static PyObject * getActiveAnalysis(PyObject *self, PyObject *args) +{ + if(ActiveAnalysis){ + + return ActiveAnalysis->getPyObject(); + } + + + Py_Return; +} + /* registration table */ From 00a3bc360a3968e421169ba695d6378bd0d776b8 Mon Sep 17 00:00:00 2001 From: jriegel Date: Sat, 6 Apr 2013 23:08:23 +0200 Subject: [PATCH 52/53] Add ViewProvider and Dialogs for Analysis object and the Netgen mesher object --- src/Mod/Fem/App/CMakeLists.txt | 7 +- src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp | 122 +++++++ src/Mod/Fem/App/FemMeshShapeNetgenObject.h | 62 ++++ src/Mod/Fem/App/FemMeshShapeObject.cpp | 320 ++++++++---------- src/Mod/Fem/App/FemMeshShapeObject.h | 6 +- src/Mod/Fem/Driver/Standard-Calculix.py | 0 src/Mod/Fem/Gui/CMakeLists.txt | 29 +- src/Mod/Fem/Gui/TaskAnalysisInfo.cpp | 85 +++++ src/Mod/Fem/Gui/TaskAnalysisInfo.h | 78 +++++ src/Mod/Fem/Gui/TaskAnalysisInfo.ui | 59 ++++ src/Mod/Fem/Gui/TaskDlgAnalysis.cpp | 118 +++++++ src/Mod/Fem/Gui/TaskDlgAnalysis.h | 72 ++++ src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp | 114 +++++++ src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h | 71 ++++ src/Mod/Fem/Gui/TaskDriver.cpp | 95 ++++++ src/Mod/Fem/Gui/TaskDriver.h | 79 +++++ src/Mod/Fem/Gui/TaskDriver.ui | 33 ++ src/Mod/Fem/Gui/TaskTetParameter.cpp | 94 +++++ src/Mod/Fem/Gui/TaskTetParameter.h | 76 +++++ src/Mod/Fem/Gui/TaskTetParameter.ui | 148 ++++++++ src/Mod/Fem/Gui/ViewProviderAnalysis.cpp | 58 ++++ src/Mod/Fem/Gui/ViewProviderAnalysis.h | 58 ++++ src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp | 51 +++ src/Mod/Fem/Gui/ViewProviderFemMeshShape.h | 58 ++++ .../Gui/ViewProviderFemMeshShapeNetgen.cpp | 54 +++ .../Fem/Gui/ViewProviderFemMeshShapeNetgen.h | 58 ++++ 26 files changed, 1817 insertions(+), 188 deletions(-) create mode 100644 src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp create mode 100644 src/Mod/Fem/App/FemMeshShapeNetgenObject.h create mode 100644 src/Mod/Fem/Driver/Standard-Calculix.py create mode 100644 src/Mod/Fem/Gui/TaskAnalysisInfo.cpp create mode 100644 src/Mod/Fem/Gui/TaskAnalysisInfo.h create mode 100644 src/Mod/Fem/Gui/TaskAnalysisInfo.ui create mode 100644 src/Mod/Fem/Gui/TaskDlgAnalysis.cpp create mode 100644 src/Mod/Fem/Gui/TaskDlgAnalysis.h create mode 100644 src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp create mode 100644 src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h create mode 100644 src/Mod/Fem/Gui/TaskDriver.cpp create mode 100644 src/Mod/Fem/Gui/TaskDriver.h create mode 100644 src/Mod/Fem/Gui/TaskDriver.ui create mode 100644 src/Mod/Fem/Gui/TaskTetParameter.cpp create mode 100644 src/Mod/Fem/Gui/TaskTetParameter.h create mode 100644 src/Mod/Fem/Gui/TaskTetParameter.ui create mode 100644 src/Mod/Fem/Gui/ViewProviderAnalysis.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderAnalysis.h create mode 100644 src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemMeshShape.h create mode 100644 src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index c2358e2ae4..4c6c985891 100755 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -54,6 +54,8 @@ SET(FemBase_SRCS FemMeshObject.h FemMeshShapeObject.cpp FemMeshShapeObject.h + FemMeshShapeNetgenObject.cpp + FemMeshShapeNetgenObject.h FemAnalysis.cpp FemAnalysis.h FemMesh.cpp @@ -102,6 +104,7 @@ SET(Fem_SRCS ${Python_SRCS} ) +FILE( GLOB Driver_Resources Driver/*.py ) add_library(Fem SHARED ${Fem_SRCS}) @@ -111,10 +114,12 @@ target_link_libraries(Fem ${Fem_LIBS}) fc_target_copy_resource(Fem ${CMAKE_SOURCE_DIR}/src/Mod/Fem ${CMAKE_BINARY_DIR}/Mod/Fem - Init.py + ${Driver_Resources} + Init.py convert2TetGen.py FemLib.py) + if(MSVC) set_target_properties(Fem PROPERTIES SUFFIX ".pyd") set_target_properties(Fem PROPERTIES DEBUG_OUTPUT_NAME "Fem_d") diff --git a/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp new file mode 100644 index 0000000000..a1a443289a --- /dev/null +++ b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "FemMeshShapeNetgenObject.h" +#include "FemMesh.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +using namespace Fem; +using namespace App; + +PROPERTY_SOURCE(Fem::FemMeshShapeNetgenObject, Fem::FemMeshShapeObject) + + +FemMeshShapeNetgenObject::FemMeshShapeNetgenObject() +{ + //ADD_PROPERTY_TYPE(Shape,(0), "Shape",Prop_None,"Shape for the analysis"); +} + +FemMeshShapeNetgenObject::~FemMeshShapeNetgenObject() +{ +} + +App::DocumentObjectExecReturn *FemMeshShapeNetgenObject::execute(void) +{ + Fem::FemMesh newMesh; + + Part::Feature *feat = Shape.getValue(); + TopoDS_Shape shape = feat->Shape.getValue(); + + NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); + + //NETGENPlugin_SimpleHypothesis_2D * tet2 = new NETGENPlugin_SimpleHypothesis_2D(hyp++,1,myGen); + //static_cast(tet2.get())->SetNumberOfSegments(5); + //static_cast(tet2.get())->SetLocalLength(0.1); + //static_cast(tet2.get())->LengthFromEdges(); + //myNetGenMesher.SetParameters(tet2); + + //NETGENPlugin_SimpleHypothesis_3D* tet= new NETGENPlugin_SimpleHypothesis_3D(hyp++,1,myGen); + //static_cast(tet.get())->LengthFromFaces(); + //static_cast(tet.get())->SetMaxElementVolume(0.1); + //myNetGenMesher.SetParameters( tet); + + myNetGenMesher.Compute(); + + + + SMESHDS_Mesh* data = const_cast(newMesh.getSMesh())->GetMeshDS(); + const SMDS_MeshInfo& info = data->GetMeshInfo(); + int numNode = info.NbNodes(); + int numTria = info.NbTriangles(); + int numQuad = info.NbQuadrangles(); + int numPoly = info.NbPolygons(); + int numVolu = info.NbVolumes(); + int numTetr = info.NbTetras(); + int numHexa = info.NbHexas(); + int numPyrd = info.NbPyramids(); + int numPris = info.NbPrisms(); + int numHedr = info.NbPolyhedrons(); + + // set the value to the object + FemMesh.setValue(newMesh); + + + return App::DocumentObject::StdReturn; +} + +//short FemMeshShapeNetgenObject::mustExecute(void) const +//{ +// return 0; +//} + +//PyObject *FemMeshShapeNetgenObject::getPyObject() +//{ +// if (PythonObject.is(Py::_None())){ +// // ref counter is set to 1 +// PythonObject = Py::Object(new DocumentObjectPy(this),true); +// } +// return Py::new_reference_to(PythonObject); +//} + +void FemMeshShapeNetgenObject::onChanged(const Property* prop) +{ + App::GeoFeature::onChanged(prop); +} diff --git a/src/Mod/Fem/App/FemMeshShapeNetgenObject.h b/src/Mod/Fem/App/FemMeshShapeNetgenObject.h new file mode 100644 index 0000000000..23b3aec62a --- /dev/null +++ b/src/Mod/Fem/App/FemMeshShapeNetgenObject.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef Fem_FemMeshShapeNetgenObject_H +#define Fem_FemMeshShapeNetgenObject_H + + +#include "FemMesh.h" +#include "FemMeshShapeObject.h" + +namespace Fem +{ + +class AppFemExport FemMeshShapeNetgenObject : public FemMeshShapeObject +{ + PROPERTY_HEADER(Fem::FemMeshShapeNetgenObject); + +public: + /// Constructor + FemMeshShapeNetgenObject(void); + virtual ~FemMeshShapeNetgenObject(); + + /// returns the type name of the ViewProvider + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemMeshShapeNetgen"; + } + virtual App::DocumentObjectExecReturn *execute(void); + + //virtual short mustExecute(void) const; + //virtual PyObject *getPyObject(void); + + //App::PropertyLink Shape; + +protected: + /// get called by the container when a property has changed + virtual void onChanged (const App::Property* prop); +}; + +} //namespace Fem + + +#endif // Fem_FemMeshShapeNetgenObject_H diff --git a/src/Mod/Fem/App/FemMeshShapeObject.cpp b/src/Mod/Fem/App/FemMeshShapeObject.cpp index 9fec365a5a..ca1bbcd7ab 100644 --- a/src/Mod/Fem/App/FemMeshShapeObject.cpp +++ b/src/Mod/Fem/App/FemMeshShapeObject.cpp @@ -32,50 +32,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include - -#include -#include - using namespace Fem; using namespace App; @@ -91,140 +47,140 @@ FemMeshShapeObject::~FemMeshShapeObject() { } -App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void) -{ - Fem::FemMesh newMesh; - - Part::Feature *feat = Shape.getValue(); - -#if 0 - TopoDS_Shape oshape = feat->Shape.getValue(); - BRepBuilderAPI_Copy copy(oshape); - const TopoDS_Shape& shape = copy.Shape(); - BRepTools::Clean(shape); // remove triangulation -#else - TopoDS_Shape shape = feat->Shape.getValue(); -#endif - - newMesh.getSMesh()->ShapeToMesh(shape); - SMESH_Gen *myGen = newMesh.getGenerator(); - - int hyp=0; -#if 0 - SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); - static_cast(len.get())->SetLength(1.0); - newMesh.addHypothesis(shape, len); - - SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); - static_cast(loc.get())->SetLength(1.0); - newMesh.addHypothesis(shape, loc); - - SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); - static_cast(area.get())->SetMaxArea(1.0); - newMesh.addHypothesis(shape, area); - - SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); - static_cast(segm.get())->SetNumberOfSegments(1); - newMesh.addHypothesis(shape, segm); - - SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); - static_cast(defl.get())->SetDeflection(0.01); - newMesh.addHypothesis(shape, defl); - - SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); - newMesh.addHypothesis(shape, reg); - - //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); - //static_cast(sel.get())->SetLength(1.0, true); - //newMesh.addHypothesis(shape, sel; - - SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); - newMesh.addHypothesis(shape, qdp); - - //SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); - //newMesh.addHypothesis(shape, q2d); - - SMESH_HypothesisPtr h3d(new StdMeshers_Hexa_3D(hyp++,1,myGen)); - newMesh.addHypothesis(shape, h3d); - - // create mesh - newMesh.compute(); -#endif -#if 0 // Surface quad mesh - SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); - static_cast(len.get())->SetLength(1.0); - newMesh.addHypothesis(shape, len); - - SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); - static_cast(loc.get())->SetLength(1.0); - newMesh.addHypothesis(shape, loc); - - SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); - static_cast(area.get())->SetMaxArea(1.0); - newMesh.addHypothesis(shape, area); - - SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); - static_cast(segm.get())->SetNumberOfSegments(1); - newMesh.addHypothesis(shape, segm); - - SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); - static_cast(defl.get())->SetDeflection(0.01); - newMesh.addHypothesis(shape, defl); - - SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); - newMesh.addHypothesis(shape, reg); - - //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); - //static_cast(sel.get())->SetLength(1.0, true); - //newMesh.addHypothesis(shape, sel; - - SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); - newMesh.addHypothesis(shape, qdp); - - SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); - newMesh.addHypothesis(shape, q2d); - - // create mesh - newMesh.compute(); -#endif -#if 1 // NETGEN test - NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); - - //NETGENPlugin_SimpleHypothesis_2D * tet2 = new NETGENPlugin_SimpleHypothesis_2D(hyp++,1,myGen); - //static_cast(tet2.get())->SetNumberOfSegments(5); - //static_cast(tet2.get())->SetLocalLength(0.1); - //static_cast(tet2.get())->LengthFromEdges(); - //myNetGenMesher.SetParameters(tet2); - - //NETGENPlugin_SimpleHypothesis_3D* tet= new NETGENPlugin_SimpleHypothesis_3D(hyp++,1,myGen); - //static_cast(tet.get())->LengthFromFaces(); - //static_cast(tet.get())->SetMaxElementVolume(0.1); - //myNetGenMesher.SetParameters( tet); - - myNetGenMesher.Compute(); -#endif - - - - SMESHDS_Mesh* data = const_cast(newMesh.getSMesh())->GetMeshDS(); - const SMDS_MeshInfo& info = data->GetMeshInfo(); - int numNode = info.NbNodes(); - int numTria = info.NbTriangles(); - int numQuad = info.NbQuadrangles(); - int numPoly = info.NbPolygons(); - int numVolu = info.NbVolumes(); - int numTetr = info.NbTetras(); - int numHexa = info.NbHexas(); - int numPyrd = info.NbPyramids(); - int numPris = info.NbPrisms(); - int numHedr = info.NbPolyhedrons(); - - // set the value to the object - FemMesh.setValue(newMesh); - - - return App::DocumentObject::StdReturn; -} +//App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void) +//{ +// Fem::FemMesh newMesh; +// +// Part::Feature *feat = Shape.getValue(); +// +//#if 0 +// TopoDS_Shape oshape = feat->Shape.getValue(); +// BRepBuilderAPI_Copy copy(oshape); +// const TopoDS_Shape& shape = copy.Shape(); +// BRepTools::Clean(shape); // remove triangulation +//#else +// TopoDS_Shape shape = feat->Shape.getValue(); +//#endif +// +// newMesh.getSMesh()->ShapeToMesh(shape); +// SMESH_Gen *myGen = newMesh.getGenerator(); +// +// int hyp=0; +//#if 0 +// SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); +// static_cast(len.get())->SetLength(1.0); +// newMesh.addHypothesis(shape, len); +// +// SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); +// static_cast(loc.get())->SetLength(1.0); +// newMesh.addHypothesis(shape, loc); +// +// SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); +// static_cast(area.get())->SetMaxArea(1.0); +// newMesh.addHypothesis(shape, area); +// +// SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); +// static_cast(segm.get())->SetNumberOfSegments(1); +// newMesh.addHypothesis(shape, segm); +// +// SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); +// static_cast(defl.get())->SetDeflection(0.01); +// newMesh.addHypothesis(shape, defl); +// +// SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); +// newMesh.addHypothesis(shape, reg); +// +// //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); +// //static_cast(sel.get())->SetLength(1.0, true); +// //newMesh.addHypothesis(shape, sel; +// +// SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); +// newMesh.addHypothesis(shape, qdp); +// +// //SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); +// //newMesh.addHypothesis(shape, q2d); +// +// SMESH_HypothesisPtr h3d(new StdMeshers_Hexa_3D(hyp++,1,myGen)); +// newMesh.addHypothesis(shape, h3d); +// +// // create mesh +// newMesh.compute(); +//#endif +//#if 0 // Surface quad mesh +// SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); +// static_cast(len.get())->SetLength(1.0); +// newMesh.addHypothesis(shape, len); +// +// SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); +// static_cast(loc.get())->SetLength(1.0); +// newMesh.addHypothesis(shape, loc); +// +// SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); +// static_cast(area.get())->SetMaxArea(1.0); +// newMesh.addHypothesis(shape, area); +// +// SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); +// static_cast(segm.get())->SetNumberOfSegments(1); +// newMesh.addHypothesis(shape, segm); +// +// SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); +// static_cast(defl.get())->SetDeflection(0.01); +// newMesh.addHypothesis(shape, defl); +// +// SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); +// newMesh.addHypothesis(shape, reg); +// +// //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); +// //static_cast(sel.get())->SetLength(1.0, true); +// //newMesh.addHypothesis(shape, sel; +// +// SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); +// newMesh.addHypothesis(shape, qdp); +// +// SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); +// newMesh.addHypothesis(shape, q2d); +// +// // create mesh +// newMesh.compute(); +//#endif +//#if 1 // NETGEN test +// NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); +// +// //NETGENPlugin_SimpleHypothesis_2D * tet2 = new NETGENPlugin_SimpleHypothesis_2D(hyp++,1,myGen); +// //static_cast(tet2.get())->SetNumberOfSegments(5); +// //static_cast(tet2.get())->SetLocalLength(0.1); +// //static_cast(tet2.get())->LengthFromEdges(); +// //myNetGenMesher.SetParameters(tet2); +// +// //NETGENPlugin_SimpleHypothesis_3D* tet= new NETGENPlugin_SimpleHypothesis_3D(hyp++,1,myGen); +// //static_cast(tet.get())->LengthFromFaces(); +// //static_cast(tet.get())->SetMaxElementVolume(0.1); +// //myNetGenMesher.SetParameters( tet); +// +// myNetGenMesher.Compute(); +//#endif +// +// +// +// SMESHDS_Mesh* data = const_cast(newMesh.getSMesh())->GetMeshDS(); +// const SMDS_MeshInfo& info = data->GetMeshInfo(); +// int numNode = info.NbNodes(); +// int numTria = info.NbTriangles(); +// int numQuad = info.NbQuadrangles(); +// int numPoly = info.NbPolygons(); +// int numVolu = info.NbVolumes(); +// int numTetr = info.NbTetras(); +// int numHexa = info.NbHexas(); +// int numPyrd = info.NbPyramids(); +// int numPris = info.NbPrisms(); +// int numHedr = info.NbPolyhedrons(); +// +// // set the value to the object +// FemMesh.setValue(newMesh); +// +// +// return App::DocumentObject::StdReturn; +//} //short FemMeshShapeObject::mustExecute(void) const //{ @@ -240,7 +196,7 @@ App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void) // return Py::new_reference_to(PythonObject); //} -void FemMeshShapeObject::onChanged(const Property* prop) -{ - App::GeoFeature::onChanged(prop); -} +//void FemMeshShapeObject::onChanged(const Property* prop) +//{ +// App::GeoFeature::onChanged(prop); +//} diff --git a/src/Mod/Fem/App/FemMeshShapeObject.h b/src/Mod/Fem/App/FemMeshShapeObject.h index cebf282b82..cac434eb8e 100644 --- a/src/Mod/Fem/App/FemMeshShapeObject.h +++ b/src/Mod/Fem/App/FemMeshShapeObject.h @@ -25,9 +25,7 @@ #define Fem_FemMeshShapeObject_H -#include "FemMesh.h" #include "FemMeshObject.h" -#include "FemMeshProperty.h" namespace Fem { @@ -45,7 +43,7 @@ public: //virtual const char* getViewProviderName(void) const { // return "FemGui::ViewProviderFemMeshShape"; //} - virtual App::DocumentObjectExecReturn *execute(void); + //virtual App::DocumentObjectExecReturn *execute(void); //virtual short mustExecute(void) const; //virtual PyObject *getPyObject(void); @@ -54,7 +52,7 @@ public: protected: /// get called by the container when a property has changed - virtual void onChanged (const App::Property* prop); + //virtual void onChanged (const App::Property* prop); }; } //namespace Fem diff --git a/src/Mod/Fem/Driver/Standard-Calculix.py b/src/Mod/Fem/Driver/Standard-Calculix.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index cd4e3ee052..6dc46ff7e7 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -36,6 +36,11 @@ set(FemGui_MOC_HDRS TaskFemConstraintForce.h TaskFemConstraintGear.h TaskFemConstraintPulley.h + TaskTetParameter.h + TaskAnalysisInfo.h + TaskDriver.h + TaskDlgAnalysis.h + TaskDlgMeshShapeNetgen.h ) fc_wrap_cpp(FemGui_MOC_SRCS ${FemGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${FemGui_MOC_SRCS}) @@ -48,6 +53,9 @@ set(FemGui_UIC_SRCS TaskFemConstraintBearing.ui TaskFemConstraintFixed.ui TaskFemConstraintForce.ui + TaskTetParameter.ui + TaskAnalysisInfo.ui + TaskDriver.ui ) qt4_wrap_ui(FemGui_UIC_HDRS ${FemGui_UIC_SRCS}) @@ -73,7 +81,7 @@ SET(FemGui_DLG_SRCS TaskFemConstraintPulley.cpp TaskFemConstraintPulley.h ) -SOURCE_GROUP("Dialogs" FILES ${FemGui_DLG_SRCS}) +SOURCE_GROUP("Constraint-Dialogs" FILES ${FemGui_DLG_SRCS}) qt4_add_resources(FemResource_SRCS Resources/Fem.qrc) @@ -82,6 +90,12 @@ SOURCE_GROUP("Resources" FILES ${FemResource_SRCS}) SET(FemGui_SRCS_ViewProvider ViewProviderFemMesh.cpp ViewProviderFemMesh.h + ViewProviderFemMeshShape.cpp + ViewProviderFemMeshShape.h + ViewProviderFemMeshShapeNetgen.cpp + ViewProviderFemMeshShapeNetgen.h + ViewProviderAnalysis.cpp + ViewProviderAnalysis.h ViewProviderSetNodes.cpp ViewProviderSetNodes.h ViewProviderSetElements.cpp @@ -114,12 +128,25 @@ SET(FemGui_SRCS_TaskBoxes TaskCreateNodeSet.ui TaskCreateNodeSet.cpp TaskCreateNodeSet.h + TaskDriver.ui + TaskDriver.cpp + TaskDriver.h + TaskAnalysisInfo.ui + TaskAnalysisInfo.cpp + TaskAnalysisInfo.h + TaskTetParameter.ui + TaskTetParameter.cpp + TaskTetParameter.h ) SOURCE_GROUP("Task_Boxes" FILES ${FemGui_SRCS_TaskBoxes}) SET(FemGui_SRCS_TaskDlg TaskDlgCreateNodeSet.h TaskDlgCreateNodeSet.cpp + TaskDlgMeshShapeNetgen.h + TaskDlgMeshShapeNetgen.cpp + TaskDlgAnalysis.h + TaskDlgAnalysis.cpp ) SOURCE_GROUP("Task_Dialogs" FILES ${FemGui_SRCS_TaskDlg}) diff --git a/src/Mod/Fem/Gui/TaskAnalysisInfo.cpp b/src/Mod/Fem/Gui/TaskAnalysisInfo.cpp new file mode 100644 index 0000000000..107375d72e --- /dev/null +++ b/src/Mod/Fem/Gui/TaskAnalysisInfo.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +#endif + +#include +#include "ui_TaskAnalysisInfo.h" +#include "TaskAnalysisInfo.h" +#include +#include +#include + + + +using namespace FemGui; +using namespace Gui; + + +TaskAnalysisInfo::TaskAnalysisInfo(Fem::FemAnalysis *pcObject,QWidget *parent) + : TaskBox(Gui::BitmapFactory().pixmap("Fem_FemMesh_createnodebypoly"), + tr("Nodes set"), + true, + parent), + pcObject(pcObject) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskAnalysisInfo(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + /* QObject::connect(ui->toolButton_Poly,SIGNAL(clicked()),this,SLOT(Poly())); + QObject::connect(ui->toolButton_Pick,SIGNAL(clicked()),this,SLOT(Pick())); + QObject::connect(ui->comboBox,SIGNAL(activated (int)),this,SLOT(SwitchMethod(int)));*/ + +} + + +void TaskAnalysisInfo::SwitchMethod(int Value) +{ + /* if(Value == 1){ + ui->groupBox_AngleSearch->setEnabled(true); + ui->toolButton_Pick->setEnabled(true); + ui->toolButton_Poly->setEnabled(false); + }else{ + ui->groupBox_AngleSearch->setEnabled(false); + ui->toolButton_Pick->setEnabled(false); + ui->toolButton_Poly->setEnabled(true); + }*/ +} + + +TaskAnalysisInfo::~TaskAnalysisInfo() +{ + delete ui; +} + + +#include "moc_TaskAnalysisInfo.cpp" diff --git a/src/Mod/Fem/Gui/TaskAnalysisInfo.h b/src/Mod/Fem/Gui/TaskAnalysisInfo.h new file mode 100644 index 0000000000..5dad4edaa9 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskAnalysisInfo.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEMGUI_TaskAnalysisInfo_H +#define FEMGUI_TaskAnalysisInfo_H + +#include +#include + +#include + + +class Ui_TaskAnalysisInfo; +class SoEventCallback; + +namespace Base { + class Polygon2D; +} +namespace App { + class Property; +} + +namespace Gui { +class ViewProvider; +class ViewVolumeProjection; +} + +namespace Fem{ + class FemAnalysis; +} + +namespace FemGui { + +class ViewProviderFemMesh; + + +class TaskAnalysisInfo : public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskAnalysisInfo(Fem::FemAnalysis *pcObject,QWidget *parent = 0); + ~TaskAnalysisInfo(); + +private Q_SLOTS: + void SwitchMethod(int Value); + +protected: + Fem::FemAnalysis *pcObject; + +private: + QWidget* proxy; + Ui_TaskAnalysisInfo* ui; +}; + +} //namespace FEMGUI_TaskAnalysisInfo_H + +#endif // GUI_TASKVIEW_TaskAnalysisInfo_H diff --git a/src/Mod/Fem/Gui/TaskAnalysisInfo.ui b/src/Mod/Fem/Gui/TaskAnalysisInfo.ui new file mode 100644 index 0000000000..9efb3bea2e --- /dev/null +++ b/src/Mod/Fem/Gui/TaskAnalysisInfo.ui @@ -0,0 +1,59 @@ + + + TaskAnalysisInfo + + + + 0 + 0 + 196 + 448 + + + + + 0 + 0 + + + + Form + + + + + + + 75 + true + + + + Meshes: + + + + + + + + + + + 75 + true + + + + Constraints + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskDlgAnalysis.cpp b/src/Mod/Fem/Gui/TaskDlgAnalysis.cpp new file mode 100644 index 0000000000..c04d5ffb2a --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgAnalysis.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "TaskDlgAnalysis.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "TaskAnalysisInfo.h" +#include "TaskDriver.h" + + +using namespace FemGui; + + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgAnalysis::TaskDlgAnalysis(Fem::FemAnalysis *obj) + : TaskDialog(),FemAnalysis(obj) +{ + driver = new TaskDriver(obj); + info = new TaskAnalysisInfo(obj); + + Content.push_back(driver); + Content.push_back(info); +} + +TaskDlgAnalysis::~TaskDlgAnalysis() +{ + +} + +//==== calls from the TaskView =============================================================== + + +void TaskDlgAnalysis::open() +{ + //select->activate(); + //Edge2TaskObject->execute(); + //param->setEdgeAndClusterNbr(Edge2TaskObject->NbrOfEdges,Edge2TaskObject->NbrOfCluster); + +} + +bool TaskDlgAnalysis::accept() +{ + //try { + // FemSetNodesObject->Nodes.setValues(param->tempSet); + // FemSetNodesObject->recompute(); + // //Gui::Document* doc = Gui::Application::Instance->activeDocument(); + // //if(doc) + // // doc->resetEdit(); + // param->MeshViewProvider->resetHighlightNodes(); + // FemSetNodesObject->Label.setValue(name->name); + // Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + // return true; + //} + //catch (const Base::Exception& e) { + // Base::Console().Warning("TaskDlgAnalysis::accept(): %s\n", e.what()); + //} + + return false; +} + +bool TaskDlgAnalysis::reject() +{ + //FemSetNodesObject->execute(); + // //Gui::Document* doc = Gui::Application::Instance->activeDocument(); + // //if(doc) + // // doc->resetEdit(); + //param->MeshViewProvider->resetHighlightNodes(); + //Gui::Command::abortCommand(); + //Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + return true; +} + +void TaskDlgAnalysis::helpRequested() +{ + +} + + +#include "moc_TaskDlgAnalysis.cpp" diff --git a/src/Mod/Fem/Gui/TaskDlgAnalysis.h b/src/Mod/Fem/Gui/TaskDlgAnalysis.h new file mode 100644 index 0000000000..185008f214 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgAnalysis.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEMGUI_TaskDlgAnalysis_H +#define FEMGUI_TaskDlgAnalysis_H + +#include + + +namespace Fem{ + class FemAnalysis; +} + +namespace FemGui { + class TaskAnalysisInfo ; + class TaskDriver; + +/// simulation dialog for the TaskView +class TaskDlgAnalysis : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgAnalysis(Fem::FemAnalysis *); + ~TaskDlgAnalysis(); + +public: + /// is called the TaskView when the dialog is opened + virtual void open(); + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user press the help button + virtual void helpRequested(); + + /// returns for Close and Help button + virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Apply; } + +protected: + TaskAnalysisInfo *info; + TaskDriver *driver; + + Fem::FemAnalysis *FemAnalysis; +}; + + + +} //namespace FemGui + +#endif // FEMGUI_TaskDlgAnalysis_H diff --git a/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp b/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp new file mode 100644 index 0000000000..dc4b03bece --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "TaskDlgMeshShapeNetgen.h" + +#include +#include +#include +#include +#include +#include +#include "ViewProviderFemMesh.h" + +#include +#include "TaskTetParameter.h" + +using namespace FemGui; + + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgMeshShapeNetgen::TaskDlgMeshShapeNetgen(Fem::FemMeshShapeNetgenObject *obj) + : TaskDialog(),FemMeshShapeNetgenObject(obj) +{ + param = new TaskTetParameter(obj); + + Content.push_back(param); +} + +TaskDlgMeshShapeNetgen::~TaskDlgMeshShapeNetgen() +{ + +} + +//==== calls from the TaskView =============================================================== + + +void TaskDlgMeshShapeNetgen::open() +{ + //select->activate(); + //Edge2TaskObject->execute(); + //param->setEdgeAndClusterNbr(Edge2TaskObject->NbrOfEdges,Edge2TaskObject->NbrOfCluster); + +} + +bool TaskDlgMeshShapeNetgen::accept() +{ + //try { + // FemSetNodesObject->Nodes.setValues(param->tempSet); + // FemSetNodesObject->recompute(); + // //Gui::Document* doc = Gui::Application::Instance->activeDocument(); + // //if(doc) + // // doc->resetEdit(); + // param->MeshViewProvider->resetHighlightNodes(); + // FemSetNodesObject->Label.setValue(name->name); + // Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + // return true; + //} + //catch (const Base::Exception& e) { + // Base::Console().Warning("TaskDlgMeshShapeNetgen::accept(): %s\n", e.what()); + //} + + return false; +} + +bool TaskDlgMeshShapeNetgen::reject() +{ + //FemSetNodesObject->execute(); + // //Gui::Document* doc = Gui::Application::Instance->activeDocument(); + // //if(doc) + // // doc->resetEdit(); + //param->MeshViewProvider->resetHighlightNodes(); + //Gui::Command::abortCommand(); + //Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + return true; +} + +void TaskDlgMeshShapeNetgen::helpRequested() +{ + +} + + +#include "moc_TaskDlgMeshShapeNetgen.cpp" diff --git a/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h b/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h new file mode 100644 index 0000000000..3958649961 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEMGUI_TaskDlgMeshShapeNetgen_H +#define FEMGUI_TaskDlgMeshShapeNetgen_H + +#include + +namespace Fem { + class FemMeshShapeNetgenObject; +} + + +namespace FemGui { + +class TaskTetParameter; + +/// simulation dialog for the TaskView +class TaskDlgMeshShapeNetgen : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgMeshShapeNetgen(Fem::FemMeshShapeNetgenObject *); + ~TaskDlgMeshShapeNetgen(); + +public: + /// is called the TaskView when the dialog is opened + virtual void open(); + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user press the help button + virtual void helpRequested(); + + /// returns for Close and Help button + virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +protected: + TaskTetParameter *param; + + Fem::FemMeshShapeNetgenObject *FemMeshShapeNetgenObject; +}; + + + +} //namespace FemGui + +#endif // FEMGUI_TaskDlgMeshShapeNetgen_H diff --git a/src/Mod/Fem/Gui/TaskDriver.cpp b/src/Mod/Fem/Gui/TaskDriver.cpp new file mode 100644 index 0000000000..3b1c8f9de5 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDriver.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +#endif + +#include +#include "ui_TaskDriver.h" +#include "TaskDriver.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +using namespace FemGui; +using namespace Gui; + + +TaskDriver::TaskDriver(Fem::FemAnalysis *pcObject,QWidget *parent) + : TaskBox(Gui::BitmapFactory().pixmap("Fem_FemMesh_createnodebypoly"), + tr("Nodes set"), + true, + parent), + pcObject(pcObject) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskDriver(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + //QObject::connect(ui->toolButton_Poly,SIGNAL(clicked()),this,SLOT(Poly())); + //QObject::connect(ui->toolButton_Pick,SIGNAL(clicked()),this,SLOT(Pick())); + //QObject::connect(ui->comboBox,SIGNAL(activated (int)),this,SLOT(SwitchMethod(int))); + +} + + + +void TaskDriver::SwitchMethod(int Value) +{ + //if(Value == 1){ + // ui->groupBox_AngleSearch->setEnabled(true); + // ui->toolButton_Pick->setEnabled(true); + // ui->toolButton_Poly->setEnabled(false); + //}else{ + // ui->groupBox_AngleSearch->setEnabled(false); + // ui->toolButton_Pick->setEnabled(false); + // ui->toolButton_Poly->setEnabled(true); + //} +} + + + + + +TaskDriver::~TaskDriver() +{ + delete ui; +} + + +#include "moc_TaskDriver.cpp" diff --git a/src/Mod/Fem/Gui/TaskDriver.h b/src/Mod/Fem/Gui/TaskDriver.h new file mode 100644 index 0000000000..c7f0b96af1 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDriver.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEMGUI_TaskDriver_H +#define FEMGUI_TaskDriver_H + +#include +#include + +#include + + +class Ui_TaskDriver; +class SoEventCallback; + +namespace Base { +class Polygon2D; +} +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +class ViewVolumeProjection; +} + +namespace Fem{ + class FemAnalysis; +} + + + +namespace FemGui { + + +class TaskDriver : public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskDriver(Fem::FemAnalysis *pcObject,QWidget *parent = 0); + ~TaskDriver(); + + +private Q_SLOTS: + void SwitchMethod(int Value); + +protected: + Fem::FemAnalysis *pcObject; + +private: + QWidget* proxy; + Ui_TaskDriver* ui; +}; + +} //namespace FemGui + +#endif // FEMGUI_TaskDriver_H diff --git a/src/Mod/Fem/Gui/TaskDriver.ui b/src/Mod/Fem/Gui/TaskDriver.ui new file mode 100644 index 0000000000..f9dd822780 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDriver.ui @@ -0,0 +1,33 @@ + + + TaskDriver + + + + 0 + 0 + 184 + 236 + + + + + 0 + 0 + + + + Form + + + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskTetParameter.cpp b/src/Mod/Fem/Gui/TaskTetParameter.cpp new file mode 100644 index 0000000000..05d318725a --- /dev/null +++ b/src/Mod/Fem/Gui/TaskTetParameter.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +#endif + +#include +#include "ui_TaskTetParameter.h" +#include "TaskTetParameter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace FemGui; +using namespace Gui; + + +TaskTetParameter::TaskTetParameter(Fem::FemMeshShapeNetgenObject *pcObject,QWidget *parent) + : TaskBox(Gui::BitmapFactory().pixmap("Fem_FemMesh_createnodebypoly"), + tr("Tet Parameter"), + true, + parent), + pcObject(pcObject) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskTetParameter(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + //QObject::connect(ui->toolButton_Poly,SIGNAL(clicked()),this,SLOT(Poly())); + //QObject::connect(ui->toolButton_Pick,SIGNAL(clicked()),this,SLOT(Pick())); + //QObject::connect(ui->comboBox,SIGNAL(activated (int)),this,SLOT(SwitchMethod(int))); + + +} + +TaskTetParameter::~TaskTetParameter() +{ + delete ui; +} + +void TaskTetParameter::SwitchMethod(int Value) +{ + //if(Value == 1){ + // ui->groupBox_AngleSearch->setEnabled(true); + // ui->toolButton_Pick->setEnabled(true); + // ui->toolButton_Poly->setEnabled(false); + //}else{ + // ui->groupBox_AngleSearch->setEnabled(false); + // ui->toolButton_Pick->setEnabled(false); + // ui->toolButton_Poly->setEnabled(true); + //} +} + + + + + + + +#include "moc_TaskTetParameter.cpp" diff --git a/src/Mod/Fem/Gui/TaskTetParameter.h b/src/Mod/Fem/Gui/TaskTetParameter.h new file mode 100644 index 0000000000..c14abb1c7e --- /dev/null +++ b/src/Mod/Fem/Gui/TaskTetParameter.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEMGUI_TaskTetParameter_H +#define FEMGUI_TaskTetParameter_H + +#include + + +class Ui_TaskTetParameter; +class SoEventCallback; + +namespace Base { +class Polygon2D; +} +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +class ViewVolumeProjection; +} +namespace Fem{ + class FemMeshShapeNetgenObject; +} + +namespace FemGui { + +class ViewProviderFemMeshShapeNetgen; + + +class TaskTetParameter : public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskTetParameter(Fem::FemMeshShapeNetgenObject *pcObject,QWidget *parent = 0); + ~TaskTetParameter(); + + ViewProviderFemMeshShapeNetgen * MeshViewProvider; + +private Q_SLOTS: + void SwitchMethod(int Value); + +protected: + Fem::FemMeshShapeNetgenObject *pcObject; + +private: + QWidget* proxy; + Ui_TaskTetParameter* ui; +}; + +} //namespace FemGui + +#endif // FEMGUI_TaskTetParameter_H diff --git a/src/Mod/Fem/Gui/TaskTetParameter.ui b/src/Mod/Fem/Gui/TaskTetParameter.ui new file mode 100644 index 0000000000..a72ea70d4e --- /dev/null +++ b/src/Mod/Fem/Gui/TaskTetParameter.ui @@ -0,0 +1,148 @@ + + + TaskTetParameter + + + + 0 + 0 + 221 + 196 + + + + + 0 + 0 + + + + Form + + + + + + + + Max. Size: + + + + + + + + + + + + Second order + + + + + + + + + Fineness: + + + + + + + 2 + + + + VeryCoarse + + + + + Coarse + + + + + Moderate + + + + + Fine + + + + + VeryFine + + + + + UserDefined + + + + + + + + Groth Rate: + + + + + + + false + + + + + + + Nbr. Segs per Edge: + + + + + + + false + + + + + + + Nbr. Segs per Radius: + + + + + + + false + + + + + + + + + Optimize + + + true + + + + + + + + diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp new file mode 100644 index 0000000000..b47ad673be --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include + +#endif + +#include "ViewProviderAnalysis.h" + +#include +#include + + +using namespace FemGui; + + + + + + + +PROPERTY_SOURCE(FemGui::ViewProviderAnalysis, Gui::ViewProviderGeometryObject) + + +ViewProviderAnalysis::ViewProviderAnalysis() +{ + + +} + +ViewProviderAnalysis::~ViewProviderAnalysis() +{ + +} + diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.h b/src/Mod/Fem/Gui/ViewProviderAnalysis.h new file mode 100644 index 0000000000..e066ce1d0a --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEM_ViewProviderAnalysis_H +#define FEM_ViewProviderAnalysis_H + +#include +#include + +class SoCoordinate3; +class SoDrawStyle; +class SoIndexedFaceSet; +class SoIndexedLineSet; +class SoShapeHints; +class SoMaterialBinding; + +namespace FemGui +{ + + + +class FemGuiExport ViewProviderAnalysis : public Gui::ViewProviderGeometryObject +{ + PROPERTY_HEADER(FemGui::ViewProviderAnalysis); + +public: + /// constructor. + ViewProviderAnalysis(); + + /// destructor. + ~ViewProviderAnalysis(); + +}; + +} //namespace FemGui + + +#endif // FEM_ViewProviderAnalysis_H diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp new file mode 100644 index 0000000000..e5cf69f23b --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include + +#endif + +#include "ViewProviderFemMeshShape.h" + + +using namespace FemGui; + + + +PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShape, Gui::ViewProviderGeometryObject) + + +ViewProviderFemMeshShape::ViewProviderFemMeshShape() +{ + +} + +ViewProviderFemMeshShape::~ViewProviderFemMeshShape() +{ + +} + + diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h new file mode 100644 index 0000000000..5793001766 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEM_ViewProviderFemMeshShape_H +#define FEM_ViewProviderFemMeshShape_H + +#include +#include + +class SoCoordinate3; +class SoDrawStyle; +class SoIndexedFaceSet; +class SoIndexedLineSet; +class SoShapeHints; +class SoMaterialBinding; + +namespace FemGui +{ + + + class FemGuiExport ViewProviderFemMeshShape : public Gui::ViewProviderGeometryObject +{ + PROPERTY_HEADER(FemGui::ViewProviderFemMeshShape); + +public: + /// constructor. + ViewProviderFemMeshShape(); + + /// destructor. + ~ViewProviderFemMeshShape(); + + +}; + +} //namespace FemGui + + +#endif // FEM_ViewProviderFemMeshShape_H diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp new file mode 100644 index 0000000000..217869299f --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include + +#endif + +#include "ViewProviderFemMeshShapeNetgen.h" + + + +using namespace FemGui; + + + + +PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShapeNetgen, Gui::ViewProviderGeometryObject) + + +ViewProviderFemMeshShapeNetgen::ViewProviderFemMeshShapeNetgen() +{ + + +} + +ViewProviderFemMeshShapeNetgen::~ViewProviderFemMeshShapeNetgen() +{ + + +} + diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h new file mode 100644 index 0000000000..882f033f56 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef FEM_ViewProviderFemMeshShapeNetgen_H +#define FEM_ViewProviderFemMeshShapeNetgen_H + +#include +#include + +class SoCoordinate3; +class SoDrawStyle; +class SoIndexedFaceSet; +class SoIndexedLineSet; +class SoShapeHints; +class SoMaterialBinding; + +namespace FemGui +{ + + +class FemGuiExport ViewProviderFemMeshShapeNetgen : public Gui::ViewProviderGeometryObject +{ + PROPERTY_HEADER(FemGui::ViewProviderFemMeshShapeNetgen); + +public: + /// constructor. + ViewProviderFemMeshShapeNetgen(); + + /// destructor. + ~ViewProviderFemMeshShapeNetgen(); + + +}; + +} //namespace FemGui + + +#endif // FEM_ViewProviderFemMeshShapeNetgen_H From 93bc329cb714f1e0ab4dbf7679c53040c14b89c6 Mon Sep 17 00:00:00 2001 From: jriegel Date: Sat, 20 Apr 2013 10:53:03 +0200 Subject: [PATCH 53/53] Adding additional objects to FEM --- src/Mod/Fem/App/AppFem.cpp | 34 +- src/Mod/Fem/App/FemAnalysis.h | 2 +- src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp | 2 + src/Mod/Fem/App/FemMeshShapeObject.cpp | 311 ++++++++++-------- src/Mod/Fem/App/FemMeshShapeObject.h | 8 +- src/Mod/Fem/Gui/AppFemGui.cpp | 30 +- src/Mod/Fem/Gui/Command.cpp | 8 +- src/Mod/Fem/Gui/ViewProviderAnalysis.cpp | 101 +++++- src/Mod/Fem/Gui/ViewProviderAnalysis.h | 13 +- src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp | 2 +- src/Mod/Fem/Gui/ViewProviderFemMeshShape.h | 4 +- .../Gui/ViewProviderFemMeshShapeNetgen.cpp | 2 +- .../Fem/Gui/ViewProviderFemMeshShapeNetgen.h | 4 +- 13 files changed, 344 insertions(+), 177 deletions(-) diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index d432b79b26..d72671f400 100755 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -33,8 +33,10 @@ #include "FemMeshPy.h" #include "FemMesh.h" #include "FemMeshProperty.h" +#include "FemAnalysis.h" #include "FemMeshObject.h" #include "FemMeshShapeObject.h" +#include "FemMeshShapeNetgenObject.h" #include "FemSetElementsObject.h" #include "FemSetFacesObject.h" @@ -111,23 +113,25 @@ void AppFemExport initFem() // call PyType_Ready, otherwise we run into a segmentation fault, later on. // This function is responsible for adding inherited slots from a type's base class. - Fem::FemMesh ::init(); - Fem::FemMeshObject ::init(); - Fem::FemMeshShapeObject ::init(); - Fem::PropertyFemMesh ::init(); + Fem::FemAnalysis ::init(); + Fem::FemMesh ::init(); + Fem::FemMeshObject ::init(); + Fem::FemMeshShapeObject ::init(); + Fem::FemMeshShapeNetgenObject ::init(); + Fem::PropertyFemMesh ::init(); - Fem::FemSetObject ::init(); - Fem::FemSetElementsObject ::init(); - Fem::FemSetFacesObject ::init(); - Fem::FemSetGeometryObject ::init(); - Fem::FemSetNodesObject ::init(); + Fem::FemSetObject ::init(); + Fem::FemSetElementsObject ::init(); + Fem::FemSetFacesObject ::init(); + Fem::FemSetGeometryObject ::init(); + Fem::FemSetNodesObject ::init(); - Fem::Constraint ::init(); - Fem::ConstraintBearing ::init(); - Fem::ConstraintFixed ::init(); - Fem::ConstraintForce ::init(); - Fem::ConstraintGear ::init(); - Fem::ConstraintPulley ::init(); + Fem::Constraint ::init(); + Fem::ConstraintBearing ::init(); + Fem::ConstraintFixed ::init(); + Fem::ConstraintForce ::init(); + Fem::ConstraintGear ::init(); + Fem::ConstraintPulley ::init(); } } // extern "C" diff --git a/src/Mod/Fem/App/FemAnalysis.h b/src/Mod/Fem/App/FemAnalysis.h index 3235effd15..6be802e758 100644 --- a/src/Mod/Fem/App/FemAnalysis.h +++ b/src/Mod/Fem/App/FemAnalysis.h @@ -43,7 +43,7 @@ public: /// returns the type name of the ViewProvider virtual const char* getViewProviderName(void) const { - return "FemGui::ViewProviderFemAnalysis"; + return "FemGui::ViewProviderAnalysis"; } virtual App::DocumentObjectExecReturn *execute(void) { return App::DocumentObject::StdReturn; diff --git a/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp index a1a443289a..2719eb0485 100644 --- a/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp +++ b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp @@ -64,6 +64,8 @@ App::DocumentObjectExecReturn *FemMeshShapeNetgenObject::execute(void) Part::Feature *feat = Shape.getValue(); TopoDS_Shape shape = feat->Shape.getValue(); + if(shape.IsNull()) + return App::DocumentObject::StdReturn; NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); diff --git a/src/Mod/Fem/App/FemMeshShapeObject.cpp b/src/Mod/Fem/App/FemMeshShapeObject.cpp index ca1bbcd7ab..bfe51c0f56 100644 --- a/src/Mod/Fem/App/FemMeshShapeObject.cpp +++ b/src/Mod/Fem/App/FemMeshShapeObject.cpp @@ -31,6 +31,49 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +#include +#include using namespace Fem; using namespace App; @@ -47,140 +90,140 @@ FemMeshShapeObject::~FemMeshShapeObject() { } -//App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void) -//{ -// Fem::FemMesh newMesh; -// -// Part::Feature *feat = Shape.getValue(); -// -//#if 0 -// TopoDS_Shape oshape = feat->Shape.getValue(); -// BRepBuilderAPI_Copy copy(oshape); -// const TopoDS_Shape& shape = copy.Shape(); -// BRepTools::Clean(shape); // remove triangulation -//#else -// TopoDS_Shape shape = feat->Shape.getValue(); -//#endif -// -// newMesh.getSMesh()->ShapeToMesh(shape); -// SMESH_Gen *myGen = newMesh.getGenerator(); -// -// int hyp=0; -//#if 0 -// SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); -// static_cast(len.get())->SetLength(1.0); -// newMesh.addHypothesis(shape, len); -// -// SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); -// static_cast(loc.get())->SetLength(1.0); -// newMesh.addHypothesis(shape, loc); -// -// SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); -// static_cast(area.get())->SetMaxArea(1.0); -// newMesh.addHypothesis(shape, area); -// -// SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); -// static_cast(segm.get())->SetNumberOfSegments(1); -// newMesh.addHypothesis(shape, segm); -// -// SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); -// static_cast(defl.get())->SetDeflection(0.01); -// newMesh.addHypothesis(shape, defl); -// -// SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); -// newMesh.addHypothesis(shape, reg); -// -// //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); -// //static_cast(sel.get())->SetLength(1.0, true); -// //newMesh.addHypothesis(shape, sel; -// -// SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); -// newMesh.addHypothesis(shape, qdp); -// -// //SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); -// //newMesh.addHypothesis(shape, q2d); -// -// SMESH_HypothesisPtr h3d(new StdMeshers_Hexa_3D(hyp++,1,myGen)); -// newMesh.addHypothesis(shape, h3d); -// -// // create mesh -// newMesh.compute(); -//#endif -//#if 0 // Surface quad mesh -// SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); -// static_cast(len.get())->SetLength(1.0); -// newMesh.addHypothesis(shape, len); -// -// SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); -// static_cast(loc.get())->SetLength(1.0); -// newMesh.addHypothesis(shape, loc); -// -// SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); -// static_cast(area.get())->SetMaxArea(1.0); -// newMesh.addHypothesis(shape, area); -// -// SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); -// static_cast(segm.get())->SetNumberOfSegments(1); -// newMesh.addHypothesis(shape, segm); -// -// SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); -// static_cast(defl.get())->SetDeflection(0.01); -// newMesh.addHypothesis(shape, defl); -// -// SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); -// newMesh.addHypothesis(shape, reg); -// -// //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); -// //static_cast(sel.get())->SetLength(1.0, true); -// //newMesh.addHypothesis(shape, sel; -// -// SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); -// newMesh.addHypothesis(shape, qdp); -// -// SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); -// newMesh.addHypothesis(shape, q2d); -// -// // create mesh -// newMesh.compute(); -//#endif -//#if 1 // NETGEN test -// NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); -// -// //NETGENPlugin_SimpleHypothesis_2D * tet2 = new NETGENPlugin_SimpleHypothesis_2D(hyp++,1,myGen); -// //static_cast(tet2.get())->SetNumberOfSegments(5); -// //static_cast(tet2.get())->SetLocalLength(0.1); -// //static_cast(tet2.get())->LengthFromEdges(); -// //myNetGenMesher.SetParameters(tet2); -// -// //NETGENPlugin_SimpleHypothesis_3D* tet= new NETGENPlugin_SimpleHypothesis_3D(hyp++,1,myGen); -// //static_cast(tet.get())->LengthFromFaces(); -// //static_cast(tet.get())->SetMaxElementVolume(0.1); -// //myNetGenMesher.SetParameters( tet); -// -// myNetGenMesher.Compute(); -//#endif -// -// -// -// SMESHDS_Mesh* data = const_cast(newMesh.getSMesh())->GetMeshDS(); -// const SMDS_MeshInfo& info = data->GetMeshInfo(); -// int numNode = info.NbNodes(); -// int numTria = info.NbTriangles(); -// int numQuad = info.NbQuadrangles(); -// int numPoly = info.NbPolygons(); -// int numVolu = info.NbVolumes(); -// int numTetr = info.NbTetras(); -// int numHexa = info.NbHexas(); -// int numPyrd = info.NbPyramids(); -// int numPris = info.NbPrisms(); -// int numHedr = info.NbPolyhedrons(); -// -// // set the value to the object -// FemMesh.setValue(newMesh); -// -// -// return App::DocumentObject::StdReturn; -//} +App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void) +{ + Fem::FemMesh newMesh; + + Part::Feature *feat = Shape.getValue(); + +#if 0 + TopoDS_Shape oshape = feat->Shape.getValue(); + BRepBuilderAPI_Copy copy(oshape); + const TopoDS_Shape& shape = copy.Shape(); + BRepTools::Clean(shape); // remove triangulation +#else + TopoDS_Shape shape = feat->Shape.getValue(); +#endif + + newMesh.getSMesh()->ShapeToMesh(shape); + SMESH_Gen *myGen = newMesh.getGenerator(); + + int hyp=0; +#if 0 + SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); + static_cast(len.get())->SetLength(1.0); + newMesh.addHypothesis(shape, len); + + SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); + static_cast(loc.get())->SetLength(1.0); + newMesh.addHypothesis(shape, loc); + + SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); + static_cast(area.get())->SetMaxArea(1.0); + newMesh.addHypothesis(shape, area); + + SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); + static_cast(segm.get())->SetNumberOfSegments(1); + newMesh.addHypothesis(shape, segm); + + SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); + static_cast(defl.get())->SetDeflection(0.01); + newMesh.addHypothesis(shape, defl); + + SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); + newMesh.addHypothesis(shape, reg); + + //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); + //static_cast(sel.get())->SetLength(1.0, true); + //newMesh.addHypothesis(shape, sel; + + SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); + newMesh.addHypothesis(shape, qdp); + + //SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); + //newMesh.addHypothesis(shape, q2d); + + SMESH_HypothesisPtr h3d(new StdMeshers_Hexa_3D(hyp++,1,myGen)); + newMesh.addHypothesis(shape, h3d); + + // create mesh + newMesh.compute(); +#endif +#if 0 // Surface quad mesh + SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen)); + static_cast(len.get())->SetLength(1.0); + newMesh.addHypothesis(shape, len); + + SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, 1, myGen)); + static_cast(loc.get())->SetLength(1.0); + newMesh.addHypothesis(shape, loc); + + SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, 1, myGen)); + static_cast(area.get())->SetMaxArea(1.0); + newMesh.addHypothesis(shape, area); + + SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, 1, myGen)); + static_cast(segm.get())->SetNumberOfSegments(1); + newMesh.addHypothesis(shape, segm); + + SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, 1, myGen)); + static_cast(defl.get())->SetDeflection(0.01); + newMesh.addHypothesis(shape, defl); + + SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, 1, myGen)); + newMesh.addHypothesis(shape, reg); + + //SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, 1, myGen)); + //static_cast(sel.get())->SetLength(1.0, true); + //newMesh.addHypothesis(shape, sel; + + SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,1,myGen)); + newMesh.addHypothesis(shape, qdp); + + SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen)); + newMesh.addHypothesis(shape, q2d); + + // create mesh + newMesh.compute(); +#endif +#if 1 // NETGEN test + NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true); + + //NETGENPlugin_SimpleHypothesis_2D * tet2 = new NETGENPlugin_SimpleHypothesis_2D(hyp++,1,myGen); + //static_cast(tet2.get())->SetNumberOfSegments(5); + //static_cast(tet2.get())->SetLocalLength(0.1); + //static_cast(tet2.get())->LengthFromEdges(); + //myNetGenMesher.SetParameters(tet2); + + //NETGENPlugin_SimpleHypothesis_3D* tet= new NETGENPlugin_SimpleHypothesis_3D(hyp++,1,myGen); + //static_cast(tet.get())->LengthFromFaces(); + //static_cast(tet.get())->SetMaxElementVolume(0.1); + //myNetGenMesher.SetParameters( tet); + + myNetGenMesher.Compute(); +#endif + + + + SMESHDS_Mesh* data = const_cast(newMesh.getSMesh())->GetMeshDS(); + const SMDS_MeshInfo& info = data->GetMeshInfo(); + int numNode = info.NbNodes(); + int numTria = info.NbTriangles(); + int numQuad = info.NbQuadrangles(); + int numPoly = info.NbPolygons(); + int numVolu = info.NbVolumes(); + int numTetr = info.NbTetras(); + int numHexa = info.NbHexas(); + int numPyrd = info.NbPyramids(); + int numPris = info.NbPrisms(); + int numHedr = info.NbPolyhedrons(); + + // set the value to the object + FemMesh.setValue(newMesh); + + + return App::DocumentObject::StdReturn; +} //short FemMeshShapeObject::mustExecute(void) const //{ diff --git a/src/Mod/Fem/App/FemMeshShapeObject.h b/src/Mod/Fem/App/FemMeshShapeObject.h index cac434eb8e..d8b5568213 100644 --- a/src/Mod/Fem/App/FemMeshShapeObject.h +++ b/src/Mod/Fem/App/FemMeshShapeObject.h @@ -40,10 +40,10 @@ public: virtual ~FemMeshShapeObject(); /// returns the type name of the ViewProvider - //virtual const char* getViewProviderName(void) const { - // return "FemGui::ViewProviderFemMeshShape"; - //} - //virtual App::DocumentObjectExecReturn *execute(void); + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemMeshShape"; + } + virtual App::DocumentObjectExecReturn *execute(void); //virtual short mustExecute(void) const; //virtual PyObject *getPyObject(void); diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index f591b18a7d..a9d4c2fe7b 100755 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -30,6 +30,9 @@ #include #include #include "ViewProviderFemMesh.h" +#include "ViewProviderFemMeshShape.h" +#include "ViewProviderFemMeshShapeNetgen.h" +#include "ViewProviderAnalysis.h" #include "ViewProviderSetNodes.h" #include "ViewProviderSetElements.h" #include "ViewProviderSetFaces.h" @@ -73,18 +76,21 @@ void FemGuiExport initFemGui() CreateFemCommands(); // addition objects - FemGui::Workbench ::init(); - FemGui::ViewProviderFemMesh ::init(); - FemGui::ViewProviderSetNodes ::init(); - FemGui::ViewProviderSetElements ::init(); - FemGui::ViewProviderSetFaces ::init(); - FemGui::ViewProviderSetGeometry ::init(); - FemGui::ViewProviderFemConstraint ::init(); - FemGui::ViewProviderFemConstraintBearing ::init(); - FemGui::ViewProviderFemConstraintFixed ::init(); - FemGui::ViewProviderFemConstraintForce ::init(); - FemGui::ViewProviderFemConstraintGear ::init(); - FemGui::ViewProviderFemConstraintPulley ::init(); + FemGui::Workbench ::init(); + FemGui::ViewProviderAnalysis ::init(); + FemGui::ViewProviderFemMesh ::init(); + FemGui::ViewProviderFemMeshShape ::init(); + FemGui::ViewProviderFemMeshShapeNetgen ::init(); + FemGui::ViewProviderSetNodes ::init(); + FemGui::ViewProviderSetElements ::init(); + FemGui::ViewProviderSetFaces ::init(); + FemGui::ViewProviderSetGeometry ::init(); + FemGui::ViewProviderFemConstraint ::init(); + FemGui::ViewProviderFemConstraintBearing ::init(); + FemGui::ViewProviderFemConstraintFixed ::init(); + FemGui::ViewProviderFemConstraintForce ::init(); + FemGui::ViewProviderFemConstraintGear ::init(); + FemGui::ViewProviderFemConstraintPulley ::init(); // add resources and reloads the translators loadFemResource(); diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index e51c49d387..4f347553cf 100755 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -120,10 +120,16 @@ void CmdFemCreateAnalysis::activated(int iMsg) Part::Feature *base = static_cast(selection[0].getObject()); + std::string AnalysisName = getUniqueObjectName("FemAnalysis"); + + std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); + openCommand("Create FEM analysis"); - doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeObject','%s')","FemShape"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); updateActive(); } diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp index b47ad673be..bcd82284ab 100644 --- a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp @@ -29,10 +29,13 @@ #endif #include "ViewProviderAnalysis.h" +#include +#include +#include -#include -#include +#include +#include "TaskDlgAnalysis.h" using namespace FemGui; @@ -42,7 +45,7 @@ using namespace FemGui; -PROPERTY_SOURCE(FemGui::ViewProviderAnalysis, Gui::ViewProviderGeometryObject) +PROPERTY_SOURCE(FemGui::ViewProviderAnalysis, Gui::ViewProviderDocumentObject) ViewProviderAnalysis::ViewProviderAnalysis() @@ -56,3 +59,95 @@ ViewProviderAnalysis::~ViewProviderAnalysis() } + +std::vector ViewProviderAnalysis::claimChildren(void)const +{ + std::vector temp(static_cast(getObject())->Member.getValues()); + + return temp; +} + +//std::vector ViewProviderAnalysis::claimChildren3D(void)const +//{ +// +// //return static_cast(getObject())->Constraints.getValues(); +// return std::vector (); +//} + +void ViewProviderAnalysis::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) +{ + //QAction* act; + //act = menu->addAction(QObject::tr("Edit pad"), receiver, member); + //act->setData(QVariant((int)ViewProvider::Default)); + //PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member); +} + +bool ViewProviderAnalysis::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + //// When double-clicking on the item for this pad the + //// object unsets and sets its edit mode without closing + //// the task panel + //Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + //TaskDlgAnalysis *anaDlg = qobject_cast(dlg); + //if (padDlg && anaDlg->getPadView() != this) + // padDlg = 0; // another pad left open its task panel + //if (dlg && !padDlg) { + // QMessageBox msgBox; + // msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + // msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + // msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + // msgBox.setDefaultButton(QMessageBox::Yes); + // int ret = msgBox.exec(); + // if (ret == QMessageBox::Yes) + // Gui::Control().closeDialog(); + // else + // return false; + //} + + // start the edit dialog +// if (padDlg) +// Gui::Control().showDialog(padDlg); +// else + + Fem::FemAnalysis* pcAna = static_cast(this->getObject()); + + Gui::Control().showDialog(new TaskDlgAnalysis(pcAna)); + + return true; + } + else { + return Gui::ViewProviderDocumentObject::setEdit(ModNum); + } +} + +void ViewProviderAnalysis::unsetEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + Gui::ViewProviderDocumentObject::unsetEdit(ModNum); + } +} + +bool ViewProviderAnalysis::onDelete(const std::vector &) +{ + //// get the support and Sketch + //PartDesign::Pad* pcPad = static_cast(getObject()); + //Sketcher::SketchObject *pcSketch = 0; + //App::DocumentObject *pcSupport = 0; + //if (pcPad->Sketch.getValue()){ + // pcSketch = static_cast(pcPad->Sketch.getValue()); + // pcSupport = pcSketch->Support.getValue(); + //} + + //// if abort command deleted the object the support is visible again + //if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch)) + // Gui::Application::Instance->getViewProvider(pcSketch)->show(); + //if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport)) + // Gui::Application::Instance->getViewProvider(pcSupport)->show(); + + return true; +} \ No newline at end of file diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.h b/src/Mod/Fem/Gui/ViewProviderAnalysis.h index e066ce1d0a..b9821267a9 100644 --- a/src/Mod/Fem/Gui/ViewProviderAnalysis.h +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.h @@ -39,7 +39,7 @@ namespace FemGui -class FemGuiExport ViewProviderAnalysis : public Gui::ViewProviderGeometryObject +class FemGuiExport ViewProviderAnalysis : public Gui::ViewProviderDocumentObject { PROPERTY_HEADER(FemGui::ViewProviderAnalysis); @@ -50,6 +50,17 @@ public: /// destructor. ~ViewProviderAnalysis(); + virtual std::vector claimChildren(void)const; + + //virtual std::vector claimChildren3D(void)const; + void setupContextMenu(QMenu*, QObject*, const char*); + + virtual bool onDelete(const std::vector &); + +protected: + virtual bool setEdit(int ModNum); + virtual void unsetEdit(int ModNum); + }; } //namespace FemGui diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp index e5cf69f23b..3fdfecebc4 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.cpp @@ -35,7 +35,7 @@ using namespace FemGui; -PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShape, Gui::ViewProviderGeometryObject) +PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShape, FemGui::ViewProviderFemMesh) ViewProviderFemMeshShape::ViewProviderFemMeshShape() diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h index 5793001766..33655999c1 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShape.h @@ -24,7 +24,7 @@ #ifndef FEM_ViewProviderFemMeshShape_H #define FEM_ViewProviderFemMeshShape_H -#include +#include "ViewProviderFemMesh.h" #include class SoCoordinate3; @@ -38,7 +38,7 @@ namespace FemGui { - class FemGuiExport ViewProviderFemMeshShape : public Gui::ViewProviderGeometryObject + class FemGuiExport ViewProviderFemMeshShape : public ViewProviderFemMesh { PROPERTY_HEADER(FemGui::ViewProviderFemMeshShape); diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp index 217869299f..02c3972362 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp @@ -37,7 +37,7 @@ using namespace FemGui; -PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShapeNetgen, Gui::ViewProviderGeometryObject) +PROPERTY_SOURCE(FemGui::ViewProviderFemMeshShapeNetgen, FemGui::ViewProviderFemMeshShape) ViewProviderFemMeshShapeNetgen::ViewProviderFemMeshShapeNetgen() diff --git a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h index 882f033f56..7c3c0468db 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h +++ b/src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h @@ -24,7 +24,7 @@ #ifndef FEM_ViewProviderFemMeshShapeNetgen_H #define FEM_ViewProviderFemMeshShapeNetgen_H -#include +#include "ViewProviderFemMeshShape.h" #include class SoCoordinate3; @@ -38,7 +38,7 @@ namespace FemGui { -class FemGuiExport ViewProviderFemMeshShapeNetgen : public Gui::ViewProviderGeometryObject +class FemGuiExport ViewProviderFemMeshShapeNetgen : public ViewProviderFemMeshShape { PROPERTY_HEADER(FemGui::ViewProviderFemMeshShapeNetgen);