More constraints working, and a few new ones

Working constraints:

PointPlaneDistance
PointInPlane
Angle
Perpendicular
Parallel

New constraints, which are composite of slvs native constraints:

PlaneCoincident
PlaneAlignment
AxialAlignment
MultiParallel
This commit is contained in:
Zheng, Lei 2017-09-25 01:07:39 +08:00
parent d26b6286e2
commit 9402201a5e
7 changed files with 1083 additions and 237 deletions

View File

@ -0,0 +1,610 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2980"
sodipodi:version="0.32"
inkscape:version="0.91 r13725"
sodipodi:docname="Assembly_ConstraintAxial.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/assembly/Assembly_constraints/Assembly_Constraint_Align_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2982">
<linearGradient
id="linearGradient3864">
<stop
id="stop3866"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2988" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3701"
gradientUnits="userSpaceOnUse"
cx="84.883324"
cy="77.042847"
fx="84.883324"
fy="77.042847"
r="19.467436"
gradientTransform="matrix(2.8492421,1.2585119,-0.4040415,0.9147407,-125.84131,-100.25805)" />
<linearGradient
id="linearGradient3007">
<stop
id="stop3009"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3011"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3377-6">
<stop
id="stop3379-2"
offset="0"
style="stop-color:#00afff;stop-opacity:1;" />
<stop
id="stop3381-4"
offset="1"
style="stop-color:#0034ff;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="77.042847"
fx="84.883324"
cy="77.042847"
cx="84.883324"
gradientTransform="matrix(2.8492421,1.2585119,-0.4040415,0.9147407,-125.84131,-100.25805)"
gradientUnits="userSpaceOnUse"
id="radialGradient3017-8"
xlink:href="#linearGradient3377-6"
inkscape:collect="always" />
<linearGradient
id="linearGradient3835">
<stop
id="stop3837"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3839"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3377-2">
<stop
id="stop3379-7"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-8"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="77.042847"
fx="84.883324"
cy="77.042847"
cx="84.883324"
gradientTransform="matrix(2.8492421,1.2585119,-0.4040415,0.9147407,-125.84131,-100.25805)"
gradientUnits="userSpaceOnUse"
id="radialGradient3017-6"
xlink:href="#linearGradient3377-2"
inkscape:collect="always" />
<linearGradient
id="linearGradient3835-1">
<stop
id="stop3837-0"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3839-9"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032"
id="radialGradient4112"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.19157613,0.46621455,-1.1364164,-0.41904304,156.5648,24.076707)"
cx="86.836884"
cy="90.601151"
fx="86.836884"
fy="90.601151"
r="19.467436" />
<linearGradient
id="linearGradient4032">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032"
id="radialGradient4114"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.19036833,-0.61386357,1.99853,-0.19092801,-47.133199,165.45559)"
cx="113.50187"
cy="65.849281"
fx="113.50187"
fy="65.849281"
r="19.467436" />
<linearGradient
id="linearGradient3171">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop3173" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop3175" />
</linearGradient>
<radialGradient
r="19.467436"
fy="65.849281"
fx="113.50187"
cy="65.849281"
cx="113.50187"
gradientTransform="matrix(0.19036833,-0.61386357,1.99853,-0.19092801,-47.133199,165.45559)"
gradientUnits="userSpaceOnUse"
id="radialGradient3180"
xlink:href="#linearGradient4032"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032-7"
id="radialGradient4112-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.19157613,0.46621455,-1.1364164,-0.41904304,162.99236,26.56694)"
cx="86.836884"
cy="90.601151"
fx="86.836884"
fy="90.601151"
r="19.467436" />
<linearGradient
id="linearGradient4032-7">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034-3" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036-6" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032-7"
id="radialGradient4114-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.19036833,-0.61386357,1.99853,-0.19092801,-47.133199,165.45559)"
cx="113.50187"
cy="65.849281"
fx="113.50187"
fy="65.849281"
r="19.467436" />
<linearGradient
id="linearGradient3171-9">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop3173-7" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop3175-5" />
</linearGradient>
<radialGradient
r="19.467436"
fy="65.849281"
fx="113.50187"
cy="65.849281"
cx="113.50187"
gradientTransform="matrix(0.19036833,-0.61386357,1.99853,-0.19092801,-47.133199,165.45559)"
gradientUnits="userSpaceOnUse"
id="radialGradient3180-6"
xlink:href="#linearGradient4032-7"
inkscape:collect="always" />
<linearGradient
id="linearGradient4032-8">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034-4" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036-3" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032-8"
id="radialGradient4114-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.19036833,-0.61386357,1.99853,-0.19092801,-47.133199,165.45559)"
cx="113.50187"
cy="65.849281"
fx="113.50187"
fy="65.849281"
r="19.467436" />
<linearGradient
id="linearGradient3171-1">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop3173-0" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop3175-3" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4032-0"
id="linearGradient3822"
x1="154.13527"
y1="33.267025"
x2="165.61629"
y2="46.429642"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4032-0">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034-37" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036-1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032-0"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="132.70454"
cy="90.193245"
fx="132.70454"
fy="90.193245"
r="19.467436"
gradientTransform="matrix(-0.08162339,1.3949072,-1.1572569,-0.26963374,245.22773,-105.44363)" />
<linearGradient
id="linearGradient3284">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop3286" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop3288" />
</linearGradient>
<radialGradient
r="19.467436"
fy="90.193245"
fx="132.70454"
cy="90.193245"
cx="132.70454"
gradientTransform="matrix(-0.08162339,1.3949072,-1.1572569,-0.26963374,245.22773,-105.44363)"
gradientUnits="userSpaceOnUse"
id="radialGradient3294"
xlink:href="#linearGradient4032-0"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3193"
id="linearGradient3191"
x1="11.757756"
y1="27.363932"
x2="21.165751"
y2="55.146343"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.99995601,0.00937982,-0.00937982,-0.99995601,39.608226,75.665997)" />
<linearGradient
id="linearGradient3193">
<stop
id="stop3195"
offset="0"
style="stop-color:#68ff00;stop-opacity:1;" />
<stop
id="stop3197"
offset="1"
style="stop-color:#078b00;stop-opacity:1;" />
</linearGradient>
<linearGradient
y2="28.943888"
x2="8.4806471"
y1="44.720886"
x1="25.351208"
gradientTransform="matrix(-0.61089092,0.00703486,-0.0057303,-0.74996724,94.131825,75.276247)"
gradientUnits="userSpaceOnUse"
id="linearGradient4353"
xlink:href="#linearGradient3193"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3801-6-7"
id="linearGradient3807-3-6"
x1="110"
y1="35"
x2="85"
y2="35"
gradientUnits="userSpaceOnUse"
spreadMethod="reflect"
gradientTransform="matrix(0.45422756,0.41994185,-0.34612298,0.37438183,-11.155749,-5.5564972)" />
<linearGradient
inkscape:collect="always"
id="linearGradient3801-6-7">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3803-7-5" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3805-5-3" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3801-6"
id="linearGradient3807-3"
x1="110"
y1="35"
x2="85"
y2="35"
gradientUnits="userSpaceOnUse"
spreadMethod="reflect"
gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.625003,1.4482735)" />
<linearGradient
inkscape:collect="always"
id="linearGradient3801-6">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3803-7" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3805-5" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3801-6"
id="linearGradient3282"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)"
spreadMethod="reflect"
x1="110"
y1="35"
x2="85"
y2="35" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3801-6"
id="linearGradient3297"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)"
spreadMethod="reflect"
x1="110"
y1="35"
x2="85"
y2="35" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="12.640625"
inkscape:cx="40.4153"
inkscape:cy="18.698293"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1375"
inkscape:window-height="876"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid3192"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2985">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:creator>
<cc:Agent>
<dc:title>[jmaustpc]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Assembly_ConstraintOpposite</dc:title>
<dc:date>2013-12-24</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintOpposite.svg</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 3.802181,61.475939 3.684839,52.991468 6.55211,55.780509 17.708271,44.311433 20.575543,47.100475 9.41938,58.569552 l 2.867271,2.789041 z"
id="path3948-2-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<g
id="g3760-8"
transform="matrix(0.39800085,0,0,0.49338099,18.710208,-4.5784768)" />
<path
style="fill:#729fcf;stroke:#0b1521;stroke-width:2.30689406;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1"
d="M 28.997729,57.628493 C 27.468459,59.282618 21.34799,56.11121 15.327279,50.54495 9.3065675,44.978691 5.6655369,39.125411 7.1948071,37.471285 L 16.378598,27.537691 38.18152,47.694898 Z"
id="path2994-3-3-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscccs" />
<path
style="fill:url(#linearGradient3807-3-6);fill-opacity:1;stroke:#729fcf;stroke-width:2.30689406;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1"
d="M 27.59251,55.172055 C 26.202267,56.675803 19.628322,51.857718 16.655,49.108826 13.681875,46.360116 8.3635134,40.183543 9.7537565,38.679795 L 17.55306,30.243723 35.391815,46.735985 Z"
id="path2994-3-6-5-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscccs" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2.30689406;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1"
d="M 33.61505,48.657811 C 30.49475,48.056483 26.330457,44.608001 23.357331,41.85929 20.384206,39.11058 16.620164,35.229169 15.776296,32.165551"
id="path2994-3-6-9-6-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csc" />
<ellipse
ry="3.9429603"
rx="14.846552"
cy="8.9656563"
cx="45.566959"
style="fill:#729fcf;stroke:#a40000;stroke-width:2.30689406;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.39999962;stroke-opacity:1"
id="path2994-2-1"
transform="matrix(0.73427561,0.67885148,-0.67885148,0.7342756,0,0)" />
<ellipse
cx="45.59362"
cy="9.1332998"
rx="12.516439"
ry="2.0296438"
style="fill:#729fcf;stroke:#ef2929;stroke-width:2.37598658;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.39999962;stroke-opacity:1"
id="path2994-2-3-2"
transform="matrix(0.73802303,0.67477552,-0.68291016,0.73050237,0,0)" />
<path
style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 43.063886,21.179171 43.181228,29.663642 40.313957,26.874601 29.157796,38.343677 26.290524,35.554635 37.446687,24.085559 34.579416,21.296517 Z"
id="path3948-2-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<g
id="g3251"
transform="matrix(0.99736843,0.9093306,-0.66413645,0.7284355,35.397806,-2.9317088)">
<g
id="g3205"
transform="translate(-0.57107468,15.488871)">
<g
id="g3287"
transform="translate(1.9999987,-13.990807)">
<path
sodipodi:nodetypes="sscccs"
inkscape:connector-curvature="0"
id="path2994-3-3"
d="m 25.571076,21.363994 c 0,2.28532 -4.924867,4.13794 -11,4.13794 -6.0751345,0 -11.0000025,-1.85262 -11.0000025,-4.13794 l -10e-7,-13.7241288 22.0000025,0 z"
style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1" />
<path
sodipodi:nodetypes="sscccs"
inkscape:connector-curvature="0"
id="path2994-3-6-5"
d="m 23.571075,20.501934 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9.0000015,-0.93831 -9.0000015,-3.01587 l -1e-6,-11.6551698 18.0000025,0 z"
style="fill:url(#linearGradient3297);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1" />
<path
sodipodi:nodetypes="csc"
inkscape:connector-curvature="0"
id="path2994-3-6-9-6"
d="m 23.571075,11.501935 c -2,1.700934 -6,1.999999 -9,1.999999 -3,0 -7.0000015,-0.299065 -9.0000015,-1.999999"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1" />
<ellipse
transform="matrix(0.52380955,0,0,0.57142854,32.904409,-6.7837776)"
id="path2994-2"
style="fill:#729fcf;stroke:#0b1521;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.39999962;stroke-opacity:1"
cx="-35"
cy="25"
rx="21"
ry="7" />
<path
sodipodi:nodetypes="csc"
inkscape:connector-curvature="0"
id="path2994-3-6-9-6-3"
d="m 25.571075,21.511129 c 0,3 -8,4 -11,4 -3,0 -11.0000003,-1 -11.0000003,-4"
style="fill:none;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.39999962;stroke-opacity:1" />
</g>
</g>
</g>
<path
style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 61.575629,2.1482687 61.692971,10.63274 58.8257,7.8436986 47.669539,19.312775 44.802267,16.523733 55.95843,5.0546565 53.091159,2.2656153 Z"
id="path3948-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -93,9 +93,14 @@
<stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5"/> <stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5"/>
</linearGradient> </linearGradient>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3282" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/> <linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3282" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3297" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/> <linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3297" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-12.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6-7-6" id="linearGradient3807-3-6-3" x1="110" y1="35" x2="85" y2="35" gradientUnits="userSpaceOnUse" spreadMethod="reflect" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.625003,1.4482735)"/>
<linearGradient inkscape:collect="always" id="linearGradient3801-6-7-6">
<stop style="stop-color:#204a87;stop-opacity:1" offset="0" id="stop3803-7-5-7"/>
<stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5-3-5"/>
</linearGradient>
</defs> </defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4.4691359" inkscape:cx="72.254434" inkscape:cy="50.969996" inkscape:current-layer="g3287" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" inkscape:window-width="1600" inkscape:window-height="837" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-global="true" inkscape:snap-bbox="true" inkscape:snap-nodes="false"> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="12.640625" inkscape:cx="48.838538" inkscape:cy="25.481539" inkscape:current-layer="g3287" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" inkscape:window-width="1600" inkscape:window-height="837" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-global="true" inkscape:snap-bbox="true" inkscape:snap-nodes="false">
<inkscape:grid type="xygrid" id="grid3192" empspacing="2" visible="true" enabled="true" snapvisiblegridlinesonly="true"/> <inkscape:grid type="xygrid" id="grid3192" empspacing="2" visible="true" enabled="true" snapvisiblegridlinesonly="true"/>
</sodipodi:namedview> </sodipodi:namedview>
<metadata id="metadata2985"> <metadata id="metadata2985">
@ -109,7 +114,7 @@
<dc:title>[jmaustpc]</dc:title> <dc:title>[jmaustpc]</dc:title>
</cc:Agent> </cc:Agent>
</dc:creator> </dc:creator>
<dc:title>Assembly_ConstraintOpposite</dc:title> <dc:title>Assembly_ConstraintParallel</dc:title>
<dc:date>2013-12-24</dc:date> <dc:date>2013-12-24</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation> <dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher> <dc:publisher>
@ -117,7 +122,7 @@
<dc:title>FreeCAD</dc:title> <dc:title>FreeCAD</dc:title>
</cc:Agent> </cc:Agent>
</dc:publisher> </dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintOpposite.svg</dc:identifier> <dc:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintParallel.svg</dc:identifier>
<dc:rights> <dc:rights>
<cc:Agent> <cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title> <dc:title>FreeCAD LGPL2+</dc:title>
@ -137,26 +142,37 @@
<g id="g3251"> <g id="g3251">
<g id="g3205" transform="translate(-0.57107468,15.488871)"> <g id="g3205" transform="translate(-0.57107468,15.488871)">
<g id="g3287" transform="translate(1.9999987,-13.990807)"> <g id="g3287" transform="translate(1.9999987,-13.990807)">
<g id="g3146" transform="matrix(-0.8660254,0.5,-0.5,-0.8660254,50.927451,50.009001)"> <g id="g3146" transform="matrix(-0.8660254,0.5,-0.5,-0.8660254,66.927451,50.009001)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165"/> <g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/> <path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3" d="m 25.571076,21.363994 c 0,2.28532 -4.924867,4.13794 -11,4.13794 -6.0751345,0 -11.0000025,-1.85262 -11.0000025,-4.13794 l -10e-7,-13.7241288 22.0000025,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3" d="m 41.571076,21.363994 c 0,2.28532 -4.924867,4.13794 -11,4.13794 -6.075135,0 -11.000003,-1.85262 -11.000003,-4.13794 l -10e-7,-13.7241288 22.000003,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5" d="m 23.571075,20.501934 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9.0000015,-0.93831 -9.0000015,-3.01587 l -1e-6,-11.6551698 18.0000025,0 z" style="fill:url(#linearGradient3297);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5" d="m 39.571075,20.501934 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9.000002,-0.93831 -9.000002,-3.01587 l -10e-7,-11.6551698 18.000003,0 z" style="fill:url(#linearGradient3297);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6" d="m 23.571075,11.501935 c -2,1.700934 -6,1.999999 -9,1.999999 -3,0 -7.0000015,-0.299065 -9.0000015,-1.999999" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6" d="m 39.571075,11.501935 c -2,1.700934 -6,1.999999 -9,1.999999 -3,0 -7.000002,-0.299065 -9.000002,-1.999999" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,32.904409,-6.7837776)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2" style="fill:#729fcf;stroke:#0b1521;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.52380955,0,0,0.57142854,48.904409,-6.7837776)" d="m -14,25 a 21,7 0 1 1 -42,0 21,7 0 1 1 42,0 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2" style="fill:#729fcf;stroke:#0b1521;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-3" d="m 25.571075,21.511129 c 0,3 -8,4 -11,4 -3,0 -11.0000003,-1 -11.0000003,-4" style="fill:none;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-3" d="m 41.571075,21.511129 c 0,3 -8,4 -11,4 -3,0 -11,-1 -11,-4" style="fill:none;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<g transform="translate(-1.428925,34.501936)" id="g3205-5-3">
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6-5" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2-6" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6-3);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9-2" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1-9" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2-1" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
</g>
<g id="g3146-7-2" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,48.927452,12.994877)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0-7"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9-0" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>
</g> </g>
</g> </g>
<g transform="translate(33.999999,34)" id="g3205-5"> </g>
<g transform="translate(35.999999,36)" id="g3205-5">
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
</g> </g>
<g id="g3146-7" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,84.356376,12.492941)"> <g id="g3146-7" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,86.356376,14.492941)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0"/> <g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/> <path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -93,14 +93,9 @@
<stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5"/> <stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5"/>
</linearGradient> </linearGradient>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3282" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/> <linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3282" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3297" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-12.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/> <linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6" id="linearGradient3297" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.053929,1.9502092)" spreadMethod="reflect" x1="110" y1="35" x2="85" y2="35"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3801-6-7-6" id="linearGradient3807-3-6-3" x1="110" y1="35" x2="85" y2="35" gradientUnits="userSpaceOnUse" spreadMethod="reflect" gradientTransform="matrix(0.45833337,0,0,0.51724135,-28.625003,1.4482735)"/>
<linearGradient inkscape:collect="always" id="linearGradient3801-6-7-6">
<stop style="stop-color:#204a87;stop-opacity:1" offset="0" id="stop3803-7-5-7"/>
<stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop3805-5-3-5"/>
</linearGradient>
</defs> </defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="12.640625" inkscape:cx="48.838538" inkscape:cy="25.481539" inkscape:current-layer="g3287" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" inkscape:window-width="1600" inkscape:window-height="837" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-global="true" inkscape:snap-bbox="true" inkscape:snap-nodes="false"> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4.4691359" inkscape:cx="72.254434" inkscape:cy="50.969996" inkscape:current-layer="g3287" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" inkscape:window-width="1600" inkscape:window-height="837" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-global="true" inkscape:snap-bbox="true" inkscape:snap-nodes="false">
<inkscape:grid type="xygrid" id="grid3192" empspacing="2" visible="true" enabled="true" snapvisiblegridlinesonly="true"/> <inkscape:grid type="xygrid" id="grid3192" empspacing="2" visible="true" enabled="true" snapvisiblegridlinesonly="true"/>
</sodipodi:namedview> </sodipodi:namedview>
<metadata id="metadata2985"> <metadata id="metadata2985">
@ -114,7 +109,7 @@
<dc:title>[jmaustpc]</dc:title> <dc:title>[jmaustpc]</dc:title>
</cc:Agent> </cc:Agent>
</dc:creator> </dc:creator>
<dc:title>Assembly_ConstraintParallel</dc:title> <dc:title>Assembly_ConstraintOpposite</dc:title>
<dc:date>2013-12-24</dc:date> <dc:date>2013-12-24</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation> <dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher> <dc:publisher>
@ -122,7 +117,7 @@
<dc:title>FreeCAD</dc:title> <dc:title>FreeCAD</dc:title>
</cc:Agent> </cc:Agent>
</dc:publisher> </dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintParallel.svg</dc:identifier> <dc:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintOpposite.svg</dc:identifier>
<dc:rights> <dc:rights>
<cc:Agent> <cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title> <dc:title>FreeCAD LGPL2+</dc:title>
@ -142,37 +137,26 @@
<g id="g3251"> <g id="g3251">
<g id="g3205" transform="translate(-0.57107468,15.488871)"> <g id="g3205" transform="translate(-0.57107468,15.488871)">
<g id="g3287" transform="translate(1.9999987,-13.990807)"> <g id="g3287" transform="translate(1.9999987,-13.990807)">
<g id="g3146" transform="matrix(-0.8660254,0.5,-0.5,-0.8660254,66.927451,50.009001)"> <g id="g3146" transform="matrix(-0.8660254,0.5,-0.5,-0.8660254,50.927451,50.009001)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165"/> <g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/> <path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3" d="m 41.571076,21.363994 c 0,2.28532 -4.924867,4.13794 -11,4.13794 -6.075135,0 -11.000003,-1.85262 -11.000003,-4.13794 l -10e-7,-13.7241288 22.000003,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3" d="m 25.571076,21.363994 c 0,2.28532 -4.924867,4.13794 -11,4.13794 -6.0751345,0 -11.0000025,-1.85262 -11.0000025,-4.13794 l -10e-7,-13.7241288 22.0000025,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5" d="m 39.571075,20.501934 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9.000002,-0.93831 -9.000002,-3.01587 l -10e-7,-11.6551698 18.000003,0 z" style="fill:url(#linearGradient3297);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5" d="m 23.571075,20.501934 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9.0000015,-0.93831 -9.0000015,-3.01587 l -1e-6,-11.6551698 18.0000025,0 z" style="fill:url(#linearGradient3297);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6" d="m 39.571075,11.501935 c -2,1.700934 -6,1.999999 -9,1.999999 -3,0 -7.000002,-0.299065 -9.000002,-1.999999" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6" d="m 23.571075,11.501935 c -2,1.700934 -6,1.999999 -9,1.999999 -3,0 -7.0000015,-0.299065 -9.0000015,-1.999999" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,48.904409,-6.7837776)" d="m -14,25 a 21,7 0 1 1 -42,0 21,7 0 1 1 42,0 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2" style="fill:#729fcf;stroke:#0b1521;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.52380955,0,0,0.57142854,32.904409,-6.7837776)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2" style="fill:#729fcf;stroke:#0b1521;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-3" d="m 41.571075,21.511129 c 0,3 -8,4 -11,4 -3,0 -11,-1 -11,-4" style="fill:none;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-3" d="m 25.571075,21.511129 c 0,3 -8,4 -11,4 -3,0 -11.0000003,-1 -11.0000003,-4" style="fill:none;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<g transform="translate(-1.428925,34.501936)" id="g3205-5-3">
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6-5" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2-6" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6-3);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9-2" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1-9" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2-1" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
</g>
<g id="g3146-7-2" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,48.927452,12.994877)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0-7"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9-0" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>
</g> </g>
</g> </g>
</g> <g transform="translate(33.999999,34)" id="g3205-5">
<g transform="translate(35.999999,36)" id="g3205-5">
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-3-6" d="m 25.000001,20.86206 c 0,2.28532 -4.924867,4.13794 -11,4.13794 C 7.924868,25 3,23.14738 3,20.86206 l -1e-6,-13.7241305 22.000001,0 z" style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="sscccs" inkscape:connector-curvature="0" id="path2994-3-6-5-2" d="m 23,20 c 0,2.07756 -5.999802,3.01587 -9,3.01587 -3,0 -9,-0.93831 -9,-3.01587 l -1e-6,-11.6551715 18.000001,0 z" style="fill:url(#linearGradient3807-3-6);fill-opacity:1;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/> <path sodipodi:nodetypes="csc" inkscape:connector-curvature="0" id="path2994-3-6-9-6-9" d="M 23,11.000001 C 21,12.700935 17,13 14,13 11,13 7,12.700935 5,11.000001" style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dashoffset:20.4"/>
<path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.52380955,0,0,0.57142854,32.333335,-7.2857133)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-1" style="fill:#729fcf;stroke:#a40000;stroke-width:3.65563059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
<path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/> <path transform="matrix(0.42857143,0,0,0.28571429,29.000001,-0.14285728)" d="m -14,25 c 0,3.865993 -9.40202,7 -21,7 -11.59798,0 -21,-3.134007 -21,-7 0,-3.865993 9.40202,-7 21,-7 11.59798,0 21,3.134007 21,7 z" sodipodi:ry="7" sodipodi:rx="21" sodipodi:cy="25" sodipodi:cx="-35" id="path2994-2-3-2" style="fill:#729fcf;stroke:#ef2929;stroke-width:5.71547556;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:20.4" sodipodi:type="arc"/>
</g> </g>
<g id="g3146-7" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,86.356376,14.492941)"> <g id="g3146-7" transform="matrix(-0.8660254,-0.5,-0.5,0.8660254,84.356376,12.492941)">
<g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0"/> <g transform="matrix(-2.0550338,1.2015287,-1.1864744,-2.0811088,4.4962146,96.61577)" id="g3165-0"/>
<path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/> <path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path3948-2-9" d="M 24.732011,29.875651 26.928162,38.071805 23.464061,36.071806 19.464067,43 15.999965,41 19.99996,34.071806 16.535859,32.071807 z" style="fill:#ef2929;stroke:#280000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"/>
</g> </g>

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -835,9 +835,7 @@ class Assembly(AsmGroup):
'{}'.format(objName(ret))) '{}'.format(objName(ret)))
return ret return ret
except IndexError: except IndexError:
if not create: if not create or obj.Group:
return # constraint group is optional, so, no exception
if obj.Group:
raise RuntimeError('Invalid assembly') raise RuntimeError('Invalid assembly')
ret = AsmConstraintGroup.make(obj) ret = AsmConstraintGroup.make(obj)
obj.setLink({0:ret}) obj.setLink({0:ret})
@ -865,6 +863,9 @@ class Assembly(AsmGroup):
def getElementGroup(self,create=False): def getElementGroup(self,create=False):
obj = self.obj obj = self.obj
if create:
# make sure previous group exists
self.getConstraintGroup(True)
try: try:
ret = obj.Group[1] ret = obj.Group[1]
checkType(ret,AsmElementGroup) checkType(ret,AsmElementGroup)
@ -878,13 +879,15 @@ class Assembly(AsmGroup):
except IndexError: except IndexError:
if not create: if not create:
raise RuntimeError('Missing element group') raise RuntimeError('Missing element group')
self.getConstraintGroup(True)
ret = AsmElementGroup.make(obj) ret = AsmElementGroup.make(obj)
obj.setLink({1:ret}) obj.setLink({1:ret})
return ret return ret
def getPartGroup(self,create=False): def getPartGroup(self,create=False):
obj = self.obj obj = self.obj
if create:
# make sure previous group exists
self.getElementGroup(True)
try: try:
ret = obj.Group[2] ret = obj.Group[2]
checkType(ret,AsmPartGroup) checkType(ret,AsmPartGroup)
@ -898,8 +901,6 @@ class Assembly(AsmGroup):
except IndexError: except IndexError:
if not create: if not create:
raise RuntimeError('Missing part group') raise RuntimeError('Missing part group')
self.getConstraintGroup(True)
self.getElementGroup(True)
ret = AsmPartGroup.make(obj) ret = AsmPartGroup.make(obj)
obj.setLink({2:ret}) obj.setLink({2:ret})
return ret return ret

View File

@ -12,6 +12,38 @@ pixmapDisabled = QPixmap(os.path.join(
iconPath,'Assembly_ConstraintDisabled.svg')) iconPath,'Assembly_ConstraintDisabled.svg'))
iconSize = (16,16) iconSize = (16,16)
def cstrName(obj):
return '{}<{}>'.format(objName(obj),obj.Type)
PropertyInfo = namedtuple('AsmPropertyInfo',
('Name','Type','Group','Doc','Enum','Getter'))
_propInfo = {}
def _propGet(obj,prop):
return getattr(obj,prop)
def _propGetValue(obj,prop):
return getattr(getattr(obj,prop),'Value')
def _makePropInfo(name,tp,doc='',enum=None,getter=_propGet,group='Constraint'):
_propInfo[name] = PropertyInfo(name,tp,group,doc,enum,getter)
_makePropInfo('Distance','App::PropertyDistance',getter=_propGetValue)
_makePropInfo('Offset','App::PropertyDistance',getter=_propGetValue)
_makePropInfo('Cascade','App::PropertyBool')
_makePropInfo('Angle','App::PropertyAngle',getter=_propGetValue)
_makePropInfo('Ratio','App::PropertyFloat')
_makePropInfo('Difference','App::PropertyFloat')
_makePropInfo('Diameter','App::PropertyFloat')
_makePropInfo('Radius','App::PropertyFloat')
_makePropInfo('Supplement','App::PropertyBool',
'If True, then the second angle is calculated as 180-angle')
_makePropInfo('AtEnd','App::PropertyBool',
'If True, then tangent at the end point, or else at the start point')
_ordinal = ['1st', '2nd', '3rd', '4th', '5th', '6th', '7th' ]
Types = [] Types = []
TypeMap = {} TypeMap = {}
TypeNameMap = {} TypeNameMap = {}
@ -23,7 +55,16 @@ class ConstraintType(type):
if cls._id in TypeMap: if cls._id in TypeMap:
raise RuntimeError( raise RuntimeError(
'Duplicate constriant type id {}'.format(cls._id)) 'Duplicate constriant type id {}'.format(cls._id))
if cls.slvsFunc(): if not cls.slvsFunc():
return
if cls._props:
for i,prop in enumerate(cls._props):
try:
cls._props[i] = _propInfo[prop]
except AttributeError:
raise RuntimeError('Unknonw property "{}" in '
'constraint type "{}"'.format(prop,cls.getName()))
TypeMap[cls._id] = cls TypeMap[cls._id] = cls
TypeNameMap[cls.getName()] = cls TypeNameMap[cls.getName()] = cls
cls._idx = len(Types) cls._idx = len(Types)
@ -34,53 +75,62 @@ class ConstraintType(type):
# PartName: text name of the part # PartName: text name of the part
# Placement: the original placement of the part # Placement: the original placement of the part
# Params: 7 parameters that defines the transformation # Params: 7 parameters that defines the transformation of this part
# RParams: 7 parameters that defines the rotation transformation of this part
# Workplane: a tuple of three entity handles, that is the workplane, the origin # Workplane: a tuple of three entity handles, that is the workplane, the origin
# point, and the normal. The workplane, defined by the origin and # point, and the normal. The workplane, defined by the origin and
# norml, is essentially the XY reference plane of the part. # norml, is essentially the XY reference plane of the part.
# EntityMap: string -> entity handle map, for caching # EntityMap: string -> entity handle map, for caching
# Group: transforming entity group handle # Group: transforming entity group handle
# X: a point entity (1,0,0) rotated by this part's placement
# Y: a point entity (0,1,0) rotated by this part's placement
# Z: a point entity (0,0,1) rotated by this part's placement
PartInfo = namedtuple('SolverPartInfo', PartInfo = namedtuple('SolverPartInfo',
('PartName','Placement','Params','Workplane','EntityMap','Group')) ('PartName','Placement','Params','RParams','Workplane','EntityMap',
'Group', 'X','Y','Z'))
def _addEntity(etype,system,partInfo,key,shape): def _p(solver,partInfo,key,shape):
key += '.{}'.format(etype) 'return a slvs handle of a transformed point derived from "shape"'
if not solver:
if utils.hasCenter(shape):
return
return 'a vertex or circular edge/face'
key += '.p'
h = partInfo.EntityMap.get(key,None) h = partInfo.EntityMap.get(key,None)
if h: if h:
logger.debug('cache {}: {}'.format(key,h)) logger.debug('cache {}: {}'.format(key,h))
return h
if etype == 'p': # point
v = utils.getElementPos(shape)
e = system.addPoint3dV(*v)
elif etype == 'n': # normal
v = utils.getElementNormal(shape)
e = system.addNormal3dV(*v)
else: else:
raise RuntimeError('unknown entity type {}'.format(etype)) v = utils.getElementPos(shape)
system = solver.system
e = system.addPoint3dV(*v)
h = system.addTransform(e,*partInfo.Params,group=partInfo.Group) h = system.addTransform(e,*partInfo.Params,group=partInfo.Group)
logger.debug('{}: {},{}, {}, {}'.format(key,h,partInfo.Group,e,v)) logger.debug('{}: {},{}, {}, {}'.format(key,h,partInfo.Group,e,v))
partInfo.EntityMap[key] = h partInfo.EntityMap[key] = h
return h return h
def _p(system,partInfo,key,shape): def _n(solver,partInfo,key,shape,retAll=False):
'return a slvs handle of a transformed point derived from "shape"' 'return a slvs handle of a transformed normal quaterion derived from shape'
if not system: if not solver:
if utils.hasCenter(shape): if utils.isPlanar(shape):
return
return 'a vertex or circular edge/face'
return _addEntity('p',system,partInfo,key,shape)
def _n(system,partInfo,key,shape):
'return a slvs handle of a transformed normal derived from "shape"'
if not system:
if utils.isAxisOfPlane(shape):
return return
return 'an edge or face with a surface normal' return 'an edge or face with a surface normal'
return _addEntity('n',system,partInfo,key,shape) key += '.n'
h = partInfo.EntityMap.get(key,None)
if h:
logger.debug('cache {}: {}'.format(key,h))
else:
system = solver.system
params = [ system.addParamV(n) for n in utils.getElementNormal(shape) ]
e = system.addNormal3d(*params)
h = system.addTransform(e,*partInfo.Params,group=partInfo.Group)
h = [h,e,params]
logger.debug('{}: {},{}'.format(key,h,partInfo.Group))
partInfo.EntityMap[key] = h
return h if retAll else h[0]
def _l(system,partInfo,key,shape,retAll=False): def _l(solver,partInfo,key,shape,retAll=False):
'return a pair of slvs handle of the end points of an edge in "shape"' 'return a pair of slvs handle of the end points of an edge in "shape"'
if not system: if not solver:
if utils.isLinearEdge(shape): if utils.isLinearEdge(shape):
return return
return 'a linear edge' return 'a linear edge'
@ -89,38 +139,52 @@ def _l(system,partInfo,key,shape,retAll=False):
if h: if h:
logger.debug('cache {}: {}'.format(key,h)) logger.debug('cache {}: {}'.format(key,h))
else: else:
system = solver.system
v = shape.Edges[0].Vertexes v = shape.Edges[0].Vertexes
p1 = system.addPoint3dV(*v[0].Point) p1 = system.addPoint3dV(*v[0].Point)
p2 = system.addPoint3dV(*v[-1].Point) p2 = system.addPoint3dV(*v[-1].Point)
h = system.addLine(p1,p2,group=partInfo.Group) h = system.addLineSegment(p1,p2,group=partInfo.Group)
h = (h,p1,p2) h = (h,p1,p2)
logger.debug('{}: {},{}'.format(key,h,partInfo.Group)) logger.debug('{}: {},{}'.format(key,h,partInfo.Group))
partInfo.EntityMap[key] = h partInfo.EntityMap[key] = h
return h if retAll else h[0] return h if retAll else h[0]
def _w(system,partInfo,key,shape,retAll=False): def _ln(solver,partInfo,key,shape,retAll=False):
'return a slvs handle of a transformed plane/workplane from "shape"' 'return a slvs handle for either a line or a normal depends on the shape'
if not system: if not solver:
if utils.isAxisOfPlane(shape): if utils.isLinearEdge(shape) or utils.isPlanar(shape):
return return
return 'an edge or face with a planar surface' return 'a linear edge or edge/face with planar surface'
if utils.isLinearEdge(shape):
return _l(solver,partInfo,key,shape,retAll)
return _n(solver,partInfo,key,shape)
def _w(solver,partInfo,key,shape,retAll=False):
'return a slvs handle of a transformed plane/workplane from "shape"'
if not solver:
if utils.isPlanar(shape):
return
return 'an edge/face with a planar surface'
key2 = key+'.w' key2 = key+'.w'
h = partInfo.EntityMap.get(key2,None) h = partInfo.EntityMap.get(key2,None)
if h: if h:
logger.debug('cache {}: {}'.format(key,h)) logger.debug('cache {}: {}'.format(key,h))
else: else:
p = _p(system,partInfo,key,shape) p = _p(solver,partInfo,key,shape)
n = _n(system,partInfo,key,shape) n = _n(solver,partInfo,key,shape)
h = system.addWorkplane(p,n,group=partInfo.Group) h = solver.system.addWorkplane(p,n,group=partInfo.Group)
h = (h,p,n) h = (h,p,n)
logger.debug('{}: {},{}'.format(key,h,partInfo.Group)) logger.debug('{}: {},{}'.format(key,h,partInfo.Group))
partInfo.EntityMap[key2] = h partInfo.EntityMap[key2] = h
return h if retAll else h[0] return h if retAll else h[0]
def _c(system,partInfo,key,shape,requireArc=False): def _wa(solver,partInfo,key,shape):
return _w(solver,partInfo,key,shape,True)
def _c(solver,partInfo,key,shape,requireArc=False):
'return a slvs handle of a transformed circle/arc derived from "shape"' 'return a slvs handle of a transformed circle/arc derived from "shape"'
if not system: if not solver:
r = utils.getElementCircular(shape) r = utils.getElementCircular(shape)
if not r or (requireArc and not isinstance(r,list,tuple)): if not r or (requireArc and not isinstance(r,list,tuple)):
return return
@ -130,46 +194,33 @@ def _c(system,partInfo,key,shape,requireArc=False):
if h: if h:
logger.debug('cache {}: {}'.format(key,h)) logger.debug('cache {}: {}'.format(key,h))
else: else:
h = _w(system,partInfo,key,shape,True) h = _w(solver,partInfo,key,shape,True)
r = utils.getElementCircular(shape) r = utils.getElementCircular(shape)
if not r: if not r:
raise RuntimeError('shape is not cicular') raise RuntimeError('shape is not cicular')
if isinstance(r,(list,tuple)): if isinstance(r,(list,tuple)):
l = _l(system,partInfo,key,shape,True) l = _l(solver,partInfo,key,shape,True)
h += l[1:] h += l[1:]
h = system.addArcOfCircleV(*h,group=partInfo.Group) h = solver.system.addArcOfCircleV(*h,group=partInfo.Group)
elif requireArc: elif requireArc:
raise RuntimeError('shape is not an arc') raise RuntimeError('shape is not an arc')
else: else:
h = h[1:] h = h[1:]
h.append(system.addDistanceV(r)) h.append(solver.addDistanceV(r))
h = system.addCircle(*h,group=partInfo.Group) h = solver.system.addCircle(*h,group=partInfo.Group)
logger.debug('{}: {},{} {}'.format(key,h,partInfo.Group,r)) logger.debug('{}: {},{} {}'.format(key,h,partInfo.Group,r))
partInfo.EntityMap[key2] = h partInfo.EntityMap[key2] = h
return h return h
def _a(system,partInfo,key,shape): def _a(solver,partInfo,key,shape):
return _c(system,partInfo,key,shape,True) return _c(solver,partInfo,key,shape,True)
_PropertyDistance = ('Value','Distance','PropertyDistance','Constraint')
_PropertyAngle = ('Value','Angle','PropertyAngle','Constraint')
_PropertyRatio = (None,'Ratio','PropertyFloat','Constraint')
_PropertyDifference = (None,'Difference','PropertyFloat','Constraint')
_PropertyDiameter = (None,'Diameter','PropertyFloat','Constraint')
_PropertyRadius = (None,'Radius','PropertyFloat','Constraint')
_PropertySupplement = (None,'Supplement','PropertyBool','Constraint',
'If True, then the second angle is calculated as 180-angle')
_PropertyAtEnd = (None,'AtEnd','PropertyBool','Constraint',
'If True, then tangent at the end point, or else at the start point')
_ordinal = ['1st', '2nd', '3rd', '4th', '5th', '6th', '7th' ]
class Base: class Base:
__metaclass__ = ConstraintType __metaclass__ = ConstraintType
_id = -1 _id = -1
_entities = [] _entityDef = []
_workplane = False _workplane = False
_props = [] _props = []
_func = None _func = None
@ -177,17 +228,20 @@ class Base:
_iconDisabled = None _iconDisabled = None
_iconName = 'Assembly_ConstraintGeneral.svg' _iconName = 'Assembly_ConstraintGeneral.svg'
def __init__(self,obj,props): def __init__(self,obj):
if obj._Type != self._id: if obj._Type != self._id:
if self._id < 0: if self._id < 0:
raise RuntimeError('invalid constraint type {} id: ' raise RuntimeError('invalid constraint type {} id: '
'{}'.format(self.__class__,self._id)) '{}'.format(self.__class__,self._id))
obj._Type = self._id obj._Type = self._id
props = obj.PropertiesList
for prop in self.__class__._props: for prop in self.__class__._props:
if prop[1] not in props: if prop.Name not in props:
obj.addProperty(*prop[1:]) obj.addProperty(prop.Type,prop.Name,prop.Group,prop.Doc)
if prop.Enum:
setattr(obj,prop.Name,prop.Enum)
else: else:
obj.setPropertyStatus(prop[1],'-Hidden') obj.setPropertyStatus(prop.Name,'-Hidden')
@classmethod @classmethod
def getName(cls): def getName(cls):
@ -203,8 +257,8 @@ class Base:
logger.error('Invalid slvs constraint "{}"'.format(cls.getName())) logger.error('Invalid slvs constraint "{}"'.format(cls.getName()))
@classmethod @classmethod
def getEntityDef(cls,group,checkCount,name=None): def getEntityDef(cls,group,checkCount,obj=None):
entities = cls._entities entities = cls._entityDef
if len(group) != len(entities): if len(group) != len(entities):
if not checkCount and len(group)<len(entities): if not checkCount and len(group)<len(entities):
return entities[:len(group)] return entities[:len(group)]
@ -212,10 +266,10 @@ class Base:
entities = list(entities) entities = list(entities)
entities.append(_w) entities.append(_w)
else: else:
if not name: if not obj:
name = cls.getName() name = cls.getName()
else: else:
name += ' of type "{}"'.format(cls.getName) name += cstrName(obj)
raise RuntimeError('Constraint {} has wrong number of ' raise RuntimeError('Constraint {} has wrong number of '
'elements {}, expecting {}'.format( 'elements {}, expecting {}'.format(
name,len(group),len(entities))) name,len(group),len(entities)))
@ -229,7 +283,7 @@ class Base:
msg = e(None,None,None,o) msg = e(None,None,None,o)
if not msg: if not msg:
continue continue
if i == len(cls._entities): if i == len(cls._entityDef):
raise RuntimeError('Constraint {} requires the optional {} ' raise RuntimeError('Constraint {} requires the optional {} '
'element to be a planar face for defining a ' 'element to be a planar face for defining a '
'workplane'.format(cls.getName(), _ordinal[i], msg)) 'workplane'.format(cls.getName(), _ordinal[i], msg))
@ -252,9 +306,11 @@ class Base:
@classmethod @classmethod
def detach(cls,obj): def detach(cls,obj):
logger.debug('detaching {}'.format(cstrName(obj)))
obj.Proxy._cstr = None
for prop in cls._props: for prop in cls._props:
# obj.removeProperty(prop[1]) # obj.setPropertyStatus(prop.Name,'Hidden')
obj.setPropertyStatus(prop[1],'Hidden') obj.removeProperty(prop.Name)
def onChanged(self,obj,prop): def onChanged(self,obj,prop):
pass pass
@ -264,25 +320,22 @@ class Base:
'''maps fcad element shape to slvs entities''' '''maps fcad element shape to slvs entities'''
ret = [] ret = []
for prop in cls._props: for prop in cls._props:
v = getattr(obj,prop[1]) ret.append(prop.Getter(obj,prop.Name))
if prop[0]:
v = getattr(v,prop[0])()
ret.append(v)
elements = obj.Proxy.getElements() elements = obj.Proxy.getElements()
entities = cls.getEntityDef(elements,True,objName(obj)) entities = cls.getEntityDef(elements,True,obj)
ret = []
for e,o in zip(entities,elements): for e,o in zip(entities,elements):
info = o.Proxy.getInfo() info = o.Proxy.getInfo()
partInfo = solver.getPartInfo(info) partInfo = solver.getPartInfo(info)
ret.append(e(solver.system,partInfo,info.Subname,info.Shape)) ret.append(e(solver,partInfo,info.Subname,info.Shape))
logger.debug('{}: {}, {}'.format(objName(obj),obj.Type,ret)) logger.debug('{} entities: {}'.format(cstrName(obj),ret))
return ret return ret
@classmethod @classmethod
def prepare(cls,obj,solver): def prepare(cls,obj,solver):
e = cls.getEntities(obj,solver) e = cls.getEntities(obj,solver)
cls._func(solver.system,*e,group=solver.group) h = cls._func(solver.system,*e,group=solver.group)
logger.debug('{} constraint: {}'.format(cstrName(obj),h))
class Locked(Base): class Locked(Base):
@ -299,186 +352,349 @@ class Locked(Base):
def check(cls,_group): def check(cls,_group):
pass pass
class BaseMulti(Base):
_id = -1
_func = True
_entityDef = [_wa]
@classmethod
def check(cls,group):
if len(group)<2:
raise RuntimeError('Constraint {} requires at least two '
'elements'.format(cls.getName()))
for o in group:
msg = cls._entityDef[0](None,None,None,o)
if msg:
raise RuntimeError('Constraint {} requires all the element '
'to be of {}'.format(cls.getName()))
return
@classmethod
def prepare(cls,obj,solver):
parts = set()
ref = None
elements = []
for e in obj.Proxy.getElements():
info = e.Proxy.getInfo()
if info.Part in parts:
logger.warn('{} skip duplicate parts {}'.format(
cstrName(obj),info.PartName))
continue
parts.add(info.Part)
if solver.isFixedPart(info):
if ref:
logger.warn('{} skip more than one fixed part {}'.format(
cstrName(obj),info.PartName))
continue
ref = info
elements.insert(0,e)
else:
elements.append(e)
if len(elements)<=1:
logger.warn('{} has no effective constraint'.format(cstrName(obj)))
return
e0 = None
for e in elements:
info = e.Proxy.getInfo()
partInfo = solver.getPartInfo(info)
if not e0:
e0 = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
else:
e = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
cls.prepareElements(obj,solver,e0,e)
class BaseCascade(BaseMulti):
@classmethod
def prepare(cls,obj,solver):
if not getattr(obj,'Cascade',True):
super(BaseCascade,cls).prepare(obj,solver)
return
prev = None
count = 0
for e in obj.Proxy.getElements():
info = e.Proxy.getInfo()
if not prev or prev.Part==info.Part:
prev = info
continue
count += 1
prevInfo = solver.getPartInfo(prev)
e1 = cls._entityDef[0](solver,prevInfo,prev.Subname,prev.Shape)
partInfo = solver.getPartInfo(info)
e2 = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
prev = info
if solver.isFixedPart(info):
e2,e1 = e1,e2
cls.prepareElements(obj,solver,e1,e2)
if not count:
logger.warn('{} has no effective constraint'.format(cstrName(obj)))
class PlaneCoincident(BaseCascade):
_id = 35
_iconName = 'Assembly_ConstraintCoincidence.svg'
_props = ["Offset", 'Cascade']
@classmethod
def prepareElements(cls,obj,solver,e1,e2):
system = solver.system
d = abs(obj.Offset.Value)
_,p1,n1 = e1
w2,p2,n2 = e2
if d>0.0:
h = system.addPointPlaneDistance(d,p1,w2,group=solver.group)
logger.debug('{}: point plane distance {},{},{}'.format(
cstrName(obj),h,p1,w2,d))
h = system.addPointsCoincident(p1,p2,w2,group=solver.group)
logger.debug('{}: points conincident {},{},{}'.format(
cstrName(obj),h,p1,p2,w2))
else:
h = system.addPointsCoincident(p1,p2,group=solver.group)
logger.debug('{}: points conincident {},{},{}'.format(
cstrName(obj),h,p1,p2))
h = system.addParallel(n1,n2,group=solver.group)
logger.debug('{}: parallel {},{},{}'.format(cstrName(obj),h,n1,n2))
class PlaneAlignment(BaseCascade):
_id = 37
_iconName = 'Assembly_ConstraintAlignment.svg'
_props = ["Offset", 'Cascade']
@classmethod
def prepareElements(cls,obj,solver,e1,e2):
system = solver.system
d = abs(obj.Offset.Value)
_,p1,n1 = e1
w2,_,n2 = e2
if d>0.0:
h = system.addPointPlaneDistance(d,p1,w2,group=solver.group)
logger.debug('{}: point plane distance {},{},{}'.format(
cstrName(obj),h,p1,w2,d))
else:
h = system.addPointInPlane(p1,w2,group=solver.group)
logger.debug('{}: point in plane {},{}'.format(
cstrName(obj),h,p1,w2))
h = system.addParallel(n1,n2,group=solver.group)
logger.debug('{}: parallel {},{},{}'.format(cstrName(obj),h,n1,n2))
class AxialAlignment(BaseMulti):
_id = 36
_iconName = 'Assembly_ConstraintAxial.svg'
@classmethod
def prepareElements(cls,obj,solver,e1,e2):
system = solver.system
_,p1,n1 = e1
w2,p2,n2 = e2
h = system.addPointsCoincident(p1,p2,w2,group=solver.group)
logger.debug('{}: points coincident {},{},{},{}'.format(
cstrName(obj),h,p1,p2,w2))
h = system.addParallel(n1,n2,group=solver.group)
logger.debug('{}: parallel {},{},{}'.format(cstrName(obj),h,n1,n2))
class SameOrientation(BaseMulti):
_id = 2
_entityDef = [_n]
_iconName = 'Assembly_ConstraintOrientation.svg'
@classmethod
def prepareElements(cls,obj,solver,n1,n2):
h = solver.system.addSameOrientation(n1,n2,group=solver.group)
logger.debug('{}: {} {},{},{}'.format(
cstrName(obj),cls.getName(),h,n1,n2))
class Angle(Base):
_id = 27
_entityDef = (_ln,_ln)
_workplane = True
_props = ["Angle","Supplement"]
_iconName = 'Assembly_ConstraintAngle.svg'
class Perpendicular(Base):
_id = 28
_entityDef = (_ln,_ln)
_workplane = True
_iconName = 'Assembly_ConstraintPerpendicular.svg'
class Parallel(Base):
_id = 29
_entityDef = (_ln,_ln)
_workplane = True
_iconName = 'Assembly_ConstraintParallel.svg'
class MultiParallel(BaseMulti):
_id = 291
_entityDef = [_ln]
_iconName = 'Assembly_ConstraintMultiParallel.svg'
@classmethod
def prepareElements(cls,obj,solver,e1,e2):
h = solver.system.addParallel(e1,e2,group=solver.group)
logger.debug('{}: {} {},{},{}'.format(
cstrName(obj),cls.getName(),h,e1,e2))
class PointsCoincident(Base): class PointsCoincident(Base):
_id = 1 _id = 1
_entities = (_p,_p) _entityDef = (_p,_p)
_workplane = True _workplane = True
_iconName = 'Assembly_ConstraintCoincidence.svg'
class SameOrientation(Base):
_id = 2
_entities = (_n,_n)
_iconName = 'Assembly_ConstraintOrientation.svg'
class PointInPlane(Base): class PointInPlane(Base):
_id = 3 _id = 3
_entities = (_p,_w) _entityDef = (_p,_w)
class PointOnLine(Base): class PointOnLine(Base):
_id = 4 _id = 4
_entities = (_p,_l) _entityDef = (_p,_l)
_workplane = True _workplane = True
class PointsDistance(Base): class PointsDistance(Base):
_id = 5 _id = 5
_entities = (_p,_p) _entityDef = (_p,_p)
_workplane = True _workplane = True
_props = [_PropertyDistance] _props = ["Distance"]
class PointsProjectDistance(Base): class PointsProjectDistance(Base):
_id = 6 _id = 6
_entities = (_p,_p,_l) _entityDef = (_p,_p,_l)
_props = [_PropertyDistance] _props = ["Distance"]
class PointPlaneDistance(Base): class PointPlaneDistance(Base):
_id = 7 _id = 7
_entities = (_p,_w) _entityDef = (_p,_w)
_props = [_PropertyDistance] _props = ["Distance"]
class PointLineDistance(Base): class PointLineDistance(Base):
_id = 8 _id = 8
_entities = (_p,_l) _entityDef = (_p,_l)
_workplane = True _workplane = True
_props = [_PropertyDistance] _props = ["Distance"]
class EqualLength(Base): class EqualLength(Base):
_id = 9 _id = 9
_entities = (_l,_l) _entityDef = (_l,_l)
_workplane = True _workplane = True
class LengthRatio(Base): class LengthRatio(Base):
_id = 10 _id = 10
_entities = (_l,_l) _entityDef = (_l,_l)
_workplane = True _workplane = True
_props = [_PropertyRatio] _props = ["Ratio"]
class LengthDifference(Base): class LengthDifference(Base):
_id = 11 _id = 11
_entities = (_l,_l) _entityDef = (_l,_l)
_workplane = True _workplane = True
_props = [_PropertyDifference] _props = ["Difference"]
class EqualLengthPointLineDistance(Base): class EqualLengthPointLineDistance(Base):
_id = 12 _id = 12
_entities = (_p,_l,_l) _entityDef = (_p,_l,_l)
_workplane = True _workplane = True
class EqualPointLineDistance(Base): class EqualPointLineDistance(Base):
_id = 13 _id = 13
_entities = (_p,_l,_p,_l) _entityDef = (_p,_l,_p,_l)
_workplane = True _workplane = True
class EqualAngle(Base): class EqualAngle(Base):
_id = 14 _id = 14
_entities = (_l,_l,_l,_l) _entityDef = (_l,_l,_l,_l)
_workplane = True _workplane = True
_props = [_PropertySupplement] _props = ["Supplement"]
class EqualLineArcLength(Base): class EqualLineArcLength(Base):
_id = 15 _id = 15
_entities = (_l,_a) _entityDef = (_l,_a)
_workplane = True _workplane = True
class Symmetric(Base): class Symmetric(Base):
_id = 16 _id = 16
_entities = (_p,_p,_w) _entityDef = (_p,_p,_w)
_workplane = True _workplane = True
class SymmetricHorizontal(Base): class SymmetricHorizontal(Base):
_id = 17 _id = 17
_entities = (_p,_p,_w) _entityDef = (_p,_p,_w)
class SymmetricVertical(Base): class SymmetricVertical(Base):
_id = 18 _id = 18
_entities = (_p,_p,_w) _entityDef = (_p,_p,_w)
class SymmetricLine(Base): class SymmetricLine(Base):
_id = 19 _id = 19
_entities = (_p,_p,_l,_w) _entityDef = (_p,_p,_l,_w)
class MidPoint(Base): class MidPoint(Base):
_id = 20 _id = 20
_entities = (_p,_p,_l) _entityDef = (_p,_p,_l)
_workplane = True _workplane = True
class PointsHorizontal(Base): class PointsHorizontal(Base):
_id = 21 _id = 21
_entities = (_p,_p) _entityDef = (_p,_p)
_workplane = True _workplane = True
class PointsVertical(Base): class PointsVertical(Base):
_id = 22 _id = 22
_entities = (_p,_p) _entityDef = (_p,_p)
_workplane = True _workplane = True
class LineHorizontal(Base): class LineHorizontal(Base):
_id = 23 _id = 23
_entities = [_l] _entityDef = [_l]
_workplane = True _workplane = True
class LineVertical(Base): class LineVertical(Base):
_id = 24 _id = 24
_entities = [_l] _entityDef = [_l]
_workplane = True _workplane = True
class Diameter(Base): class Diameter(Base):
_id = 25 _id = 25
_entities = [_c] _entityDef = [_c]
_prop = [_PropertyDiameter] _prop = ["Diameter"]
class PointOnCircle(Base): class PointOnCircle(Base):
_id = 26 _id = 26
_entities = [_p,_c] _entityDef = [_p,_c]
class Angle(Base):
_id = 27
_entities = (_l,_l)
_workplane = True
_props = [_PropertyAngle,_PropertySupplement]
class Perpendicular(Base):
_id = 28
_entities = (_l,_l)
_workplane = True
class Parallel(Base):
_id = 29
_entities = (_l,_l)
_workplane = True
class ArcLineTangent(Base): class ArcLineTangent(Base):
_id = 30 _id = 30
_entities = (_c,_l) _entityDef = (_c,_l)
_props = [_PropertyAtEnd] _props = ["AtEnd"]
# class CubicLineTangent(Base): # class CubicLineTangent(Base):
@ -491,13 +707,13 @@ class ArcLineTangent(Base):
class EqualRadius(Base): class EqualRadius(Base):
_id = 33 _id = 33
_entities = (_c,_c) _entityDef = (_c,_c)
_props = [_PropertyRadius] _props = ["Radius"]
class WhereDragged(Base): class WhereDragged(Base):
_id = 34 _id = 34
_entities = [_p] _entityDef = [_p]
_workplane = True _workplane = True
@ -505,20 +721,12 @@ TypeEnum = namedtuple('AsmConstraintEnum',
(c.getName() for c in Types))(*range(len(Types))) (c.getName() for c in Types))(*range(len(Types)))
def attach(obj,checkType=True): def attach(obj,checkType=True):
props = None
if checkType: if checkType:
props = obj.PropertiesList if 'Type' not in obj.PropertiesList:
# if not '_Type' in props: # The 'Type' property here is to let user select the type in
# raise RuntimeError('Object "{}" has no _Type property'.format( # property editor. It is marked as 'transient' to avoid having to
# objName(obj))) # save the enumeration value for each object.
if 'Type' in props: obj.addProperty("App::PropertyEnumeration","Type","Base",'',2)
raise RuntimeError('Object {} already as property "Type"'.format(
objName(obj)))
# The 'Type' property here is to let user select the type in property
# editor. It is marked as 'transient' to avoid having to save the
# enumeration value for each object.
obj.addProperty("App::PropertyEnumeration","Type","Constraint",'',2)
obj.Type = TypeEnum._fields obj.Type = TypeEnum._fields
idx = 0 idx = 0
try: try:
@ -531,19 +739,21 @@ def attach(obj,checkType=True):
constraintType = TypeNameMap[obj.Type] constraintType = TypeNameMap[obj.Type]
cstr = getattr(obj.Proxy,'_cstr',None) cstr = getattr(obj.Proxy,'_cstr',None)
if type(cstr) is not constraintType: if type(cstr) is not constraintType:
logger.debug('attaching {}, {} -> {}'.format(
objName(obj),type(cstr).__name__,constraintType.__name__),frame=1)
if cstr: if cstr:
cstr.detach(obj) cstr.detach(obj)
if not props: obj.Proxy._cstr = constraintType(obj)
props = obj.PropertiesList
obj.Proxy._cstr = constraintType(obj,props)
obj.ViewObject.signalChangeIcon() obj.ViewObject.signalChangeIcon()
def onChanged(obj,prop): def onChanged(obj,prop):
if prop == 'Type': if prop == 'Type':
if hasattr(obj.Proxy,'_cstr'):
attach(obj,False) attach(obj,False)
return return
elif prop == '_Type': elif prop == '_Type':
if hasattr(obj,'Type'):
obj.Type = TypeMap[obj._Type]._idx obj.Type = TypeMap[obj._Type]._idx
return return
elif prop == 'Disabled': elif prop == 'Disabled':
@ -564,4 +774,6 @@ def isLocked(obj):
return not obj.Disabled and isinstance(obj.Proxy._cstr,Locked) return not obj.Disabled and isinstance(obj.Proxy._cstr,Locked)
def getIcon(obj): def getIcon(obj):
return obj.Proxy._cstr.getIcon(obj) cstr = getattr(obj.Proxy,'_cstr',None)
if cstr:
return cstr.getIcon(obj)

View File

@ -3,6 +3,7 @@ import asm3.slvs as slvs
import asm3.assembly as asm import asm3.assembly as asm
from asm3.utils import logger, objName, isSamePlacement from asm3.utils import logger, objName, isSamePlacement
import asm3.constraint as constraint import asm3.constraint as constraint
import random
class AsmSolver(object): class AsmSolver(object):
def __init__(self,assembly,reportFailed): def __init__(self,assembly,reportFailed):
@ -26,6 +27,16 @@ class AsmSolver(object):
self._entityMap = {} self._entityMap = {}
self._fixedParts = set() self._fixedParts = set()
self.system.GroupHandle = self._fixedGroup
# convenience constants
self.zero = self.system.addParamV(0)
self.one = self.system.addParamV(1)
self.o = self.system.addPoint3d(self.zero,self.zero,self.zero)
self.x = self.system.addPoint3d(self.one,self.zero,self.zero)
self.y = self.system.addPoint3d(self.zero,self.one,self.zero)
self.z = self.system.addPoint3d(self.zero,self.zero,self.one)
for cstr in cstrs: for cstr in cstrs:
if constraint.isLocked(cstr): if constraint.isLocked(cstr):
constraint.prepare(cstr,self) constraint.prepare(cstr,self)
@ -35,15 +46,16 @@ class AsmSolver(object):
logger.debug('lock first part {}'.format(objName(parts[0]))) logger.debug('lock first part {}'.format(objName(parts[0])))
self._fixedParts.add(parts[0]) self._fixedParts.add(parts[0])
self.system.GroupHandle = self._fixedGroup
for cstr in self._cstrs: for cstr in self._cstrs:
logger.debug('preparing {}, type {}'.format( logger.debug('preparing {}, type {}'.format(
objName(cstr),cstr.Type)) objName(cstr),cstr.Type))
self.system.GroupHandle += 1 self.system.GroupHandle += 1
handle = self.system.ConstraintHandle handle = self.system.ConstraintHandle
constraint.prepare(cstr,self) constraint.prepare(cstr,self)
for h in range(handle,self.system.ConstraintHandle): handles = range(handle+1,self.system.ConstraintHandle+1)
self._cstrMap[h+1] = cstr for h in handles:
self._cstrMap[h] = cstr
logger.debug('{} handles: {}'.format(objName(cstr),handles))
logger.debug('solving {}'.format(objName(assembly))) logger.debug('solving {}'.format(objName(assembly)))
ret = self.system.solve(group=self.group,reportFailed=reportFailed) ret = self.system.solve(group=self.group,reportFailed=reportFailed)
@ -64,13 +76,15 @@ class AsmSolver(object):
objName(cstr),cstr.Type,h) objName(cstr),cstr.Type,h)
logger.error(msg) logger.error(msg)
if ret==1: if ret==1:
reason = 'redundent constraints' reason = 'inconsistent constraints'
elif ret==2: elif ret==2:
reason = 'not converging' reason = 'not converging'
elif ret==3: elif ret==3:
reason = 'too many unknowns' reason = 'too many unknowns'
elif ret==4: elif ret==4:
reason = 'init failed' reason = 'init failed'
elif ret==5:
reason = 'redundent constraints'
else: else:
reason = 'unknown failure' reason = 'unknown failure'
raise RuntimeError('Failed to solve {}: {}'.format( raise RuntimeError('Failed to solve {}: {}'.format(
@ -96,6 +110,9 @@ class AsmSolver(object):
for doc in undoDocs: for doc in undoDocs:
doc.commitTransaction() doc.commitTransaction()
def isFixedPart(self,info):
return info.Part in self._fixedParts
def addFixedPart(self,info): def addFixedPart(self,info):
logger.debug('lock part ' + info.PartName) logger.debug('lock part ' + info.PartName)
self._fixedParts.add(info.Part) self._fixedParts.add(info.Part)
@ -127,12 +144,13 @@ class AsmSolver(object):
entityMap = {} entityMap = {}
self._entityMap[info.Object] = entityMap self._entityMap[info.Object] = entityMap
pla = info.Placement
if info.Part in self._fixedParts: if info.Part in self._fixedParts:
g = self._fixedGroup g = self._fixedGroup
else: else:
g = self.group g = self.group
q = info.Placement.Rotation.Q q = pla.Rotation.Q
vals = list(info.Placement.Base) + [q[3],q[0],q[1],q[2]] vals = list(pla.Base) + [q[3],q[0],q[1],q[2]]
params = [self.system.addParamV(v,g) for v in vals] params = [self.system.addParamV(v,g) for v in vals]
p = self.system.addPoint3d(*params[:3],group=g) p = self.system.addPoint3d(*params[:3],group=g)
@ -140,11 +158,16 @@ class AsmSolver(object):
w = self.system.addWorkplane(p,n,group=g) w = self.system.addWorkplane(p,n,group=g)
h = (w,p,n) h = (w,p,n)
logger.debug('{} {}, {}, {}, {}'.format( rparams = [self.zero]*3 + params[3:]
info.PartName,info.Placement,h,params,vals)) x = self.system.addTransform(self.x,*rparams,group=g)
y = self.system.addTransform(self.y,*rparams,group=g)
z = self.system.addTransform(self.z,*rparams,group=g)
partInfo = constraint.PartInfo(info.PartName, info.Placement.copy(),
params,rparams,h,entityMap,g,x,y,z)
logger.debug('{}'.format(partInfo))
partInfo = constraint.PartInfo(
info.PartName, info.Placement.copy(),params,h,entityMap,g)
self._partMap[info.Part] = partInfo self._partMap[info.Part] = partInfo
return partInfo return partInfo

View File

@ -33,19 +33,19 @@ def getElement(obj,tp):
if isinstance(obj,tp): if isinstance(obj,tp):
return obj return obj
def isPlane(obj): def isPlanar(obj):
face = getElement(obj,Part.Face) shape = getElement(obj,(Part.Face,Part.Edge))
if not face: if not shape:
return False return False
elif str(face.Surface) == '<Plane object>': elif str(shape.Surface) == '<Plane object>':
return True return True
elif hasattr(face.Surface,'Radius'): elif hasattr(shape.Surface,'Radius'):
return False return False
elif str(face.Surface).startswith('<SurfaceOfRevolution'): elif str(shape.Surface).startswith('<SurfaceOfRevolution'):
return False return False
else: else:
_plane_norm,_plane_pos,error = fit_plane_to_surface1(face.Surface) _plane_norm,_plane_pos,error = fit_plane_to_surface1(shape.Surface)
error_normalized = error / face.BoundBox.DiagonalLength error_normalized = error / shape.BoundBox.DiagonalLength
return error_normalized < 10**-6 return error_normalized < 10**-6
def isCylindricalPlane(obj): def isCylindricalPlane(obj):