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"/>
</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"/>
<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>
<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"/>
</sodipodi:namedview>
<metadata id="metadata2985">
@ -109,7 +114,7 @@
<dc:title>[jmaustpc]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Assembly_ConstraintOpposite</dc:title>
<dc:title>Assembly_ConstraintParallel</dc:title>
<dc:date>2013-12-24</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
@ -117,7 +122,7 @@
<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:identifier>FreeCAD/src/Mod/Assembly/Gui/Resources/icons/constraints/Assembly_ConstraintParallel.svg</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
@ -137,26 +142,37 @@
<g id="g3251">
<g id="g3205" transform="translate(-0.57107468,15.488871)">
<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"/>
<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>
<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 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 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,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 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="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 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 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,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 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 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-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 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"/>
</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"/>
<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>

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"/>
</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,-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>
<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="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"/>
</sodipodi:namedview>
<metadata id="metadata2985">
@ -114,7 +109,7 @@
<dc:title>[jmaustpc]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Assembly_ConstraintParallel</dc:title>
<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>
@ -122,7 +117,7 @@
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</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>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
@ -142,37 +137,26 @@
<g id="g3251">
<g id="g3205" transform="translate(-0.57107468,15.488871)">
<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"/>
<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>
<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 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 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,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 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>
<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 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 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,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 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>
</g>
</g>
<g transform="translate(35.999999,36)" id="g3205-5">
<g transform="translate(33.999999,34)" 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-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 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"/>
</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"/>
<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>

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

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

View File

@ -12,6 +12,38 @@ pixmapDisabled = QPixmap(os.path.join(
iconPath,'Assembly_ConstraintDisabled.svg'))
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 = []
TypeMap = {}
TypeNameMap = {}
@ -23,64 +55,82 @@ class ConstraintType(type):
if cls._id in TypeMap:
raise RuntimeError(
'Duplicate constriant type id {}'.format(cls._id))
if cls.slvsFunc():
TypeMap[cls._id] = cls
TypeNameMap[cls.getName()] = cls
cls._idx = len(Types)
logger.debug('register constraint "{}":{},{}'.format(
cls.getName(),cls._id,cls._idx))
Types.append(cls)
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
TypeNameMap[cls.getName()] = cls
cls._idx = len(Types)
logger.debug('register constraint "{}":{},{}'.format(
cls.getName(),cls._id,cls._idx))
Types.append(cls)
# PartName: text name 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
# point, and the normal. The workplane, defined by the origin and
# norml, is essentially the XY reference plane of the part.
# EntityMap: string -> entity handle map, for caching
# 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',
('PartName','Placement','Params','Workplane','EntityMap','Group'))
('PartName','Placement','Params','RParams','Workplane','EntityMap',
'Group', 'X','Y','Z'))
def _addEntity(etype,system,partInfo,key,shape):
key += '.{}'.format(etype)
h = partInfo.EntityMap.get(key,None)
if 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:
raise RuntimeError('unknown entity type {}'.format(etype))
h = system.addTransform(e,*partInfo.Params,group=partInfo.Group)
logger.debug('{}: {},{}, {}, {}'.format(key,h,partInfo.Group,e,v))
partInfo.EntityMap[key] = h
return h
def _p(system,partInfo,key,shape):
def _p(solver,partInfo,key,shape):
'return a slvs handle of a transformed point derived from "shape"'
if not system:
if not solver:
if utils.hasCenter(shape):
return
return 'a vertex or circular edge/face'
return _addEntity('p',system,partInfo,key,shape)
key += '.p'
h = partInfo.EntityMap.get(key,None)
if h:
logger.debug('cache {}: {}'.format(key,h))
else:
v = utils.getElementPos(shape)
system = solver.system
e = system.addPoint3dV(*v)
h = system.addTransform(e,*partInfo.Params,group=partInfo.Group)
logger.debug('{}: {},{}, {}, {}'.format(key,h,partInfo.Group,e,v))
partInfo.EntityMap[key] = h
return h
def _n(system,partInfo,key,shape):
'return a slvs handle of a transformed normal derived from "shape"'
if not system:
if utils.isAxisOfPlane(shape):
def _n(solver,partInfo,key,shape,retAll=False):
'return a slvs handle of a transformed normal quaterion derived from shape'
if not solver:
if utils.isPlanar(shape):
return
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"'
if not system:
if not solver:
if utils.isLinearEdge(shape):
return
return 'a linear edge'
@ -89,38 +139,52 @@ def _l(system,partInfo,key,shape,retAll=False):
if h:
logger.debug('cache {}: {}'.format(key,h))
else:
system = solver.system
v = shape.Edges[0].Vertexes
p1 = system.addPoint3dV(*v[0].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)
logger.debug('{}: {},{}'.format(key,h,partInfo.Group))
partInfo.EntityMap[key] = h
return h if retAll else h[0]
def _w(system,partInfo,key,shape,retAll=False):
'return a slvs handle of a transformed plane/workplane from "shape"'
if not system:
if utils.isAxisOfPlane(shape):
def _ln(solver,partInfo,key,shape,retAll=False):
'return a slvs handle for either a line or a normal depends on the shape'
if not solver:
if utils.isLinearEdge(shape) or utils.isPlanar(shape):
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'
h = partInfo.EntityMap.get(key2,None)
if h:
logger.debug('cache {}: {}'.format(key,h))
else:
p = _p(system,partInfo,key,shape)
n = _n(system,partInfo,key,shape)
h = system.addWorkplane(p,n,group=partInfo.Group)
p = _p(solver,partInfo,key,shape)
n = _n(solver,partInfo,key,shape)
h = solver.system.addWorkplane(p,n,group=partInfo.Group)
h = (h,p,n)
logger.debug('{}: {},{}'.format(key,h,partInfo.Group))
partInfo.EntityMap[key2] = h
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"'
if not system:
if not solver:
r = utils.getElementCircular(shape)
if not r or (requireArc and not isinstance(r,list,tuple)):
return
@ -130,46 +194,33 @@ def _c(system,partInfo,key,shape,requireArc=False):
if h:
logger.debug('cache {}: {}'.format(key,h))
else:
h = _w(system,partInfo,key,shape,True)
h = _w(solver,partInfo,key,shape,True)
r = utils.getElementCircular(shape)
if not r:
raise RuntimeError('shape is not cicular')
if isinstance(r,(list,tuple)):
l = _l(system,partInfo,key,shape,True)
l = _l(solver,partInfo,key,shape,True)
h += l[1:]
h = system.addArcOfCircleV(*h,group=partInfo.Group)
h = solver.system.addArcOfCircleV(*h,group=partInfo.Group)
elif requireArc:
raise RuntimeError('shape is not an arc')
else:
h = h[1:]
h.append(system.addDistanceV(r))
h = system.addCircle(*h,group=partInfo.Group)
h.append(solver.addDistanceV(r))
h = solver.system.addCircle(*h,group=partInfo.Group)
logger.debug('{}: {},{} {}'.format(key,h,partInfo.Group,r))
partInfo.EntityMap[key2] = h
return h
def _a(system,partInfo,key,shape):
return _c(system,partInfo,key,shape,True)
def _a(solver,partInfo,key,shape):
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:
__metaclass__ = ConstraintType
_id = -1
_entities = []
_entityDef = []
_workplane = False
_props = []
_func = None
@ -177,17 +228,20 @@ class Base:
_iconDisabled = None
_iconName = 'Assembly_ConstraintGeneral.svg'
def __init__(self,obj,props):
def __init__(self,obj):
if obj._Type != self._id:
if self._id < 0:
raise RuntimeError('invalid constraint type {} id: '
'{}'.format(self.__class__,self._id))
obj._Type = self._id
props = obj.PropertiesList
for prop in self.__class__._props:
if prop[1] not in props:
obj.addProperty(*prop[1:])
if prop.Name not in props:
obj.addProperty(prop.Type,prop.Name,prop.Group,prop.Doc)
if prop.Enum:
setattr(obj,prop.Name,prop.Enum)
else:
obj.setPropertyStatus(prop[1],'-Hidden')
obj.setPropertyStatus(prop.Name,'-Hidden')
@classmethod
def getName(cls):
@ -203,8 +257,8 @@ class Base:
logger.error('Invalid slvs constraint "{}"'.format(cls.getName()))
@classmethod
def getEntityDef(cls,group,checkCount,name=None):
entities = cls._entities
def getEntityDef(cls,group,checkCount,obj=None):
entities = cls._entityDef
if len(group) != len(entities):
if not checkCount and len(group)<len(entities):
return entities[:len(group)]
@ -212,10 +266,10 @@ class Base:
entities = list(entities)
entities.append(_w)
else:
if not name:
if not obj:
name = cls.getName()
else:
name += ' of type "{}"'.format(cls.getName)
name += cstrName(obj)
raise RuntimeError('Constraint {} has wrong number of '
'elements {}, expecting {}'.format(
name,len(group),len(entities)))
@ -229,7 +283,7 @@ class Base:
msg = e(None,None,None,o)
if not msg:
continue
if i == len(cls._entities):
if i == len(cls._entityDef):
raise RuntimeError('Constraint {} requires the optional {} '
'element to be a planar face for defining a '
'workplane'.format(cls.getName(), _ordinal[i], msg))
@ -252,9 +306,11 @@ class Base:
@classmethod
def detach(cls,obj):
logger.debug('detaching {}'.format(cstrName(obj)))
obj.Proxy._cstr = None
for prop in cls._props:
# obj.removeProperty(prop[1])
obj.setPropertyStatus(prop[1],'Hidden')
# obj.setPropertyStatus(prop.Name,'Hidden')
obj.removeProperty(prop.Name)
def onChanged(self,obj,prop):
pass
@ -264,25 +320,22 @@ class Base:
'''maps fcad element shape to slvs entities'''
ret = []
for prop in cls._props:
v = getattr(obj,prop[1])
if prop[0]:
v = getattr(v,prop[0])()
ret.append(v)
ret.append(prop.Getter(obj,prop.Name))
elements = obj.Proxy.getElements()
entities = cls.getEntityDef(elements,True,objName(obj))
ret = []
entities = cls.getEntityDef(elements,True,obj)
for e,o in zip(entities,elements):
info = o.Proxy.getInfo()
partInfo = solver.getPartInfo(info)
ret.append(e(solver.system,partInfo,info.Subname,info.Shape))
logger.debug('{}: {}, {}'.format(objName(obj),obj.Type,ret))
ret.append(e(solver,partInfo,info.Subname,info.Shape))
logger.debug('{} entities: {}'.format(cstrName(obj),ret))
return ret
@classmethod
def prepare(cls,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):
@ -299,186 +352,349 @@ class Locked(Base):
def check(cls,_group):
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):
_id = 1
_entities = (_p,_p)
_entityDef = (_p,_p)
_workplane = True
_iconName = 'Assembly_ConstraintCoincidence.svg'
class SameOrientation(Base):
_id = 2
_entities = (_n,_n)
_iconName = 'Assembly_ConstraintOrientation.svg'
class PointInPlane(Base):
_id = 3
_entities = (_p,_w)
_entityDef = (_p,_w)
class PointOnLine(Base):
_id = 4
_entities = (_p,_l)
_entityDef = (_p,_l)
_workplane = True
class PointsDistance(Base):
_id = 5
_entities = (_p,_p)
_entityDef = (_p,_p)
_workplane = True
_props = [_PropertyDistance]
_props = ["Distance"]
class PointsProjectDistance(Base):
_id = 6
_entities = (_p,_p,_l)
_props = [_PropertyDistance]
_entityDef = (_p,_p,_l)
_props = ["Distance"]
class PointPlaneDistance(Base):
_id = 7
_entities = (_p,_w)
_props = [_PropertyDistance]
_entityDef = (_p,_w)
_props = ["Distance"]
class PointLineDistance(Base):
_id = 8
_entities = (_p,_l)
_entityDef = (_p,_l)
_workplane = True
_props = [_PropertyDistance]
_props = ["Distance"]
class EqualLength(Base):
_id = 9
_entities = (_l,_l)
_entityDef = (_l,_l)
_workplane = True
class LengthRatio(Base):
_id = 10
_entities = (_l,_l)
_entityDef = (_l,_l)
_workplane = True
_props = [_PropertyRatio]
_props = ["Ratio"]
class LengthDifference(Base):
_id = 11
_entities = (_l,_l)
_entityDef = (_l,_l)
_workplane = True
_props = [_PropertyDifference]
_props = ["Difference"]
class EqualLengthPointLineDistance(Base):
_id = 12
_entities = (_p,_l,_l)
_entityDef = (_p,_l,_l)
_workplane = True
class EqualPointLineDistance(Base):
_id = 13
_entities = (_p,_l,_p,_l)
_entityDef = (_p,_l,_p,_l)
_workplane = True
class EqualAngle(Base):
_id = 14
_entities = (_l,_l,_l,_l)
_entityDef = (_l,_l,_l,_l)
_workplane = True
_props = [_PropertySupplement]
_props = ["Supplement"]
class EqualLineArcLength(Base):
_id = 15
_entities = (_l,_a)
_entityDef = (_l,_a)
_workplane = True
class Symmetric(Base):
_id = 16
_entities = (_p,_p,_w)
_entityDef = (_p,_p,_w)
_workplane = True
class SymmetricHorizontal(Base):
_id = 17
_entities = (_p,_p,_w)
_entityDef = (_p,_p,_w)
class SymmetricVertical(Base):
_id = 18
_entities = (_p,_p,_w)
_entityDef = (_p,_p,_w)
class SymmetricLine(Base):
_id = 19
_entities = (_p,_p,_l,_w)
_entityDef = (_p,_p,_l,_w)
class MidPoint(Base):
_id = 20
_entities = (_p,_p,_l)
_entityDef = (_p,_p,_l)
_workplane = True
class PointsHorizontal(Base):
_id = 21
_entities = (_p,_p)
_entityDef = (_p,_p)
_workplane = True
class PointsVertical(Base):
_id = 22
_entities = (_p,_p)
_entityDef = (_p,_p)
_workplane = True
class LineHorizontal(Base):
_id = 23
_entities = [_l]
_entityDef = [_l]
_workplane = True
class LineVertical(Base):
_id = 24
_entities = [_l]
_entityDef = [_l]
_workplane = True
class Diameter(Base):
_id = 25
_entities = [_c]
_prop = [_PropertyDiameter]
_entityDef = [_c]
_prop = ["Diameter"]
class PointOnCircle(Base):
_id = 26
_entities = [_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
_entityDef = [_p,_c]
class ArcLineTangent(Base):
_id = 30
_entities = (_c,_l)
_props = [_PropertyAtEnd]
_entityDef = (_c,_l)
_props = ["AtEnd"]
# class CubicLineTangent(Base):
@ -491,13 +707,13 @@ class ArcLineTangent(Base):
class EqualRadius(Base):
_id = 33
_entities = (_c,_c)
_props = [_PropertyRadius]
_entityDef = (_c,_c)
_props = ["Radius"]
class WhereDragged(Base):
_id = 34
_entities = [_p]
_entityDef = [_p]
_workplane = True
@ -505,20 +721,12 @@ TypeEnum = namedtuple('AsmConstraintEnum',
(c.getName() for c in Types))(*range(len(Types)))
def attach(obj,checkType=True):
props = None
if checkType:
props = obj.PropertiesList
# if not '_Type' in props:
# raise RuntimeError('Object "{}" has no _Type property'.format(
# objName(obj)))
if 'Type' in props:
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)
if 'Type' not in obj.PropertiesList:
# 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","Base",'',2)
obj.Type = TypeEnum._fields
idx = 0
try:
@ -531,20 +739,22 @@ def attach(obj,checkType=True):
constraintType = TypeNameMap[obj.Type]
cstr = getattr(obj.Proxy,'_cstr',None)
if type(cstr) is not constraintType:
logger.debug('attaching {}, {} -> {}'.format(
objName(obj),type(cstr).__name__,constraintType.__name__),frame=1)
if cstr:
cstr.detach(obj)
if not props:
props = obj.PropertiesList
obj.Proxy._cstr = constraintType(obj,props)
obj.Proxy._cstr = constraintType(obj)
obj.ViewObject.signalChangeIcon()
def onChanged(obj,prop):
if prop == 'Type':
attach(obj,False)
if hasattr(obj.Proxy,'_cstr'):
attach(obj,False)
return
elif prop == '_Type':
obj.Type = TypeMap[obj._Type]._idx
if hasattr(obj,'Type'):
obj.Type = TypeMap[obj._Type]._idx
return
elif prop == 'Disabled':
obj.ViewObject.signalChangeIcon()
@ -564,4 +774,6 @@ def isLocked(obj):
return not obj.Disabled and isinstance(obj.Proxy._cstr,Locked)
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
from asm3.utils import logger, objName, isSamePlacement
import asm3.constraint as constraint
import random
class AsmSolver(object):
def __init__(self,assembly,reportFailed):
@ -26,6 +27,16 @@ class AsmSolver(object):
self._entityMap = {}
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:
if constraint.isLocked(cstr):
constraint.prepare(cstr,self)
@ -35,15 +46,16 @@ class AsmSolver(object):
logger.debug('lock first part {}'.format(objName(parts[0])))
self._fixedParts.add(parts[0])
self.system.GroupHandle = self._fixedGroup
for cstr in self._cstrs:
logger.debug('preparing {}, type {}'.format(
objName(cstr),cstr.Type))
self.system.GroupHandle += 1
handle = self.system.ConstraintHandle
constraint.prepare(cstr,self)
for h in range(handle,self.system.ConstraintHandle):
self._cstrMap[h+1] = cstr
handles = range(handle+1,self.system.ConstraintHandle+1)
for h in handles:
self._cstrMap[h] = cstr
logger.debug('{} handles: {}'.format(objName(cstr),handles))
logger.debug('solving {}'.format(objName(assembly)))
ret = self.system.solve(group=self.group,reportFailed=reportFailed)
@ -64,13 +76,15 @@ class AsmSolver(object):
objName(cstr),cstr.Type,h)
logger.error(msg)
if ret==1:
reason = 'redundent constraints'
reason = 'inconsistent constraints'
elif ret==2:
reason = 'not converging'
elif ret==3:
reason = 'too many unknowns'
elif ret==4:
reason = 'init failed'
elif ret==5:
reason = 'redundent constraints'
else:
reason = 'unknown failure'
raise RuntimeError('Failed to solve {}: {}'.format(
@ -96,6 +110,9 @@ class AsmSolver(object):
for doc in undoDocs:
doc.commitTransaction()
def isFixedPart(self,info):
return info.Part in self._fixedParts
def addFixedPart(self,info):
logger.debug('lock part ' + info.PartName)
self._fixedParts.add(info.Part)
@ -127,12 +144,13 @@ class AsmSolver(object):
entityMap = {}
self._entityMap[info.Object] = entityMap
pla = info.Placement
if info.Part in self._fixedParts:
g = self._fixedGroup
else:
g = self.group
q = info.Placement.Rotation.Q
vals = list(info.Placement.Base) + [q[3],q[0],q[1],q[2]]
q = pla.Rotation.Q
vals = list(pla.Base) + [q[3],q[0],q[1],q[2]]
params = [self.system.addParamV(v,g) for v in vals]
p = self.system.addPoint3d(*params[:3],group=g)
@ -140,11 +158,16 @@ class AsmSolver(object):
w = self.system.addWorkplane(p,n,group=g)
h = (w,p,n)
logger.debug('{} {}, {}, {}, {}'.format(
info.PartName,info.Placement,h,params,vals))
rparams = [self.zero]*3 + params[3:]
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
return partInfo

View File

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