Assembly: Simulation implementation

This commit is contained in:
Aik-Siong Koh
2024-08-28 10:01:11 -06:00
committed by Max Wilfinger
parent 3e70f7244d
commit 5d143d1f59
28 changed files with 6187 additions and 15 deletions

View File

@@ -0,0 +1,387 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="64"
height="64"
id="svg1307"
sodipodi:version="0.32"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="media-playback-start-back.svg"
inkscape:export-filename="/home/lapo/Desktop/Grafica/Icone/media-actions-outlines.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1309">
<linearGradient
inkscape:collect="always"
id="linearGradient3851">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3853" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3855" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3823">
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="0"
id="stop3825" />
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="1"
id="stop3827" />
</linearGradient>
<linearGradient
id="linearGradient2684">
<stop
id="stop2686"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop2688"
offset="1"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2584">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2586" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2588" />
</linearGradient>
<linearGradient
id="linearGradient5075">
<stop
style="stop-color:#adb0a8;stop-opacity:1;"
offset="0"
id="stop5077" />
<stop
style="stop-color:#464744;stop-opacity:1"
offset="1"
id="stop5079" />
</linearGradient>
<linearGradient
id="linearGradient3340">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3342" />
<stop
style="stop-color:#ffffff;stop-opacity:0.62886596;"
offset="1"
id="stop3344" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5075"
id="linearGradient2306"
gradientUnits="userSpaceOnUse"
x1="71.288956"
y1="124.11652"
x2="70.826942"
y2="95"
gradientTransform="translate(-105.00042,-71.09425)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2684"
id="linearGradient2690"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.128181,0,0,1.128181,-113.99314,-83.36009)"
x1="70.913956"
y1="101.74152"
x2="70.951942"
y2="88.923729" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="12.5"
x2="6.75"
y1="0.5"
x1="6.75"
id="linearGradient7035"
xlink:href="#linearGradient7029"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
r="9.3095722"
fy="431.19708"
fx="466.73566"
cy="431.19708"
cx="466.73566"
id="radialGradient6052"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient2438"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient24732"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
id="linearGradient17794">
<stop
id="stop17798"
offset="0"
style="stop-color:#f18383;stop-opacity:1;" />
<stop
style="stop-color:#ed6767;stop-opacity:1;"
offset="0.3807947"
id="stop8006" />
<stop
id="stop17796"
offset="1"
style="stop-color:#e62323;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient7029">
<stop
id="stop7031"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop7033"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3851"
id="linearGradient3857"
x1="35.599998"
y1="60.799999"
x2="27.200001"
y2="27.199999"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3823"
id="linearGradient629"
gradientUnits="userSpaceOnUse"
x1="23"
y1="34"
x2="15"
y2="-4"
gradientTransform="matrix(-0.98460592,0,0,1,63.92303,-0.2323838)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
inkscape:pageopacity="0.0000000"
inkscape:pageshadow="2"
inkscape:zoom="10.421875"
inkscape:cx="9.7391304"
inkscape:cy="39.82009"
inkscape:current-layer="g627"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:grid-points="true"
fill="#555753"
showguides="false"
inkscape:guide-bbox="true"
guidetolerance="1px"
stroke="#555753"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="0"
inkscape:window-y="0"
showborder="true"
inkscape:showpageshadow="true"
borderlayer="true"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0">
<sodipodi:guide
orientation="horizontal"
position="38.996647"
id="guide2194" />
<sodipodi:guide
orientation="horizontal"
position="9.0140845"
id="guide2196" />
<sodipodi:guide
orientation="vertical"
position="9.0140845"
id="guide2198" />
<sodipodi:guide
orientation="vertical"
position="38.975184"
id="guide2200" />
<sodipodi:guide
orientation="horizontal"
position="22.988281"
id="guide2202" />
<sodipodi:guide
orientation="vertical"
position="23.908786"
id="guide2204" />
<sodipodi:guide
orientation="vertical"
position="157.99417"
id="guide4332" />
<sodipodi:guide
orientation="horizontal"
position="-36.062446"
id="guide4334" />
<sodipodi:guide
orientation="horizontal"
position="-58.02695"
id="guide4336" />
<sodipodi:guide
orientation="vertical"
position="180.00287"
id="guide4338" />
<sodipodi:guide
orientation="vertical"
position="107.92217"
id="guide4417" />
<sodipodi:guide
orientation="vertical"
position="129.93087"
id="guide4419" />
<sodipodi:guide
orientation="horizontal"
position="19.996875"
id="guide5106" />
<sodipodi:guide
orientation="horizontal"
position="63.039674"
id="guide5119" />
<sodipodi:guide
orientation="horizontal"
position="49.066305"
id="guide5121" />
<sodipodi:guide
orientation="horizontal"
position="-86.007168"
id="guide5307" />
<sodipodi:guide
orientation="horizontal"
position="-108.09009"
id="guide5309" />
<sodipodi:guide
orientation="horizontal"
position="-100.15429"
id="guide3111" />
<inkscape:grid
id="GridFromPre046Settings"
type="xygrid"
originx="0"
originy="0"
spacingx="1"
spacingy="1"
color="#3f3fff"
empcolor="#3f3fff"
opacity="0.15"
empopacity="0.38"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata1312">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Lapo Calamandrei</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:subject>
<rdf:Bag>
<rdf:li>play</rdf:li>
<rdf:li>media</rdf:li>
<rdf:li>music</rdf:li>
<rdf:li>video</rdf:li>
<rdf:li>player</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:contributor>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="contorno"
style="display:none"
transform="translate(0,16)" />
<g
id="g627"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
style="display:inline"
transform="translate(0,16)">
<path
style="fill:#8ae234;stroke:#172a04;stroke-width:1.98454;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 60.969212,44.767616 v -58 l -57.107143,29 z"
id="path623"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="display:inline;fill:url(#linearGradient629);fill-opacity:1;stroke:#8ae234;stroke-width:1.98454;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 59,41.535232 V -10 L 8.2182494,15.767616 Z"
id="path625"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,450 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="64"
height="64"
id="svg1307"
sodipodi:version="0.32"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="media-playback-step-back.svg"
inkscape:export-filename="/home/lapo/Desktop/Grafica/Icone/media-actions-outlines.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1309">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1006"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1"
unit="px"
method="auto"
mode="F"
radius="1"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect7179"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1"
unit="px"
method="auto"
mode="F"
radius="1"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<linearGradient
inkscape:collect="always"
id="linearGradient3851">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3853" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3855" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3823">
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="0"
id="stop3825" />
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="1"
id="stop3827" />
</linearGradient>
<linearGradient
id="linearGradient2684">
<stop
id="stop2686"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop2688"
offset="1"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2584">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2586" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2588" />
</linearGradient>
<linearGradient
id="linearGradient5075">
<stop
style="stop-color:#adb0a8;stop-opacity:1;"
offset="0"
id="stop5077" />
<stop
style="stop-color:#464744;stop-opacity:1"
offset="1"
id="stop5079" />
</linearGradient>
<linearGradient
id="linearGradient3340">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3342" />
<stop
style="stop-color:#ffffff;stop-opacity:0.62886596;"
offset="1"
id="stop3344" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5075"
id="linearGradient2306"
gradientUnits="userSpaceOnUse"
x1="71.288956"
y1="124.11652"
x2="70.826942"
y2="95"
gradientTransform="translate(-105.00042,-71.09425)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2684"
id="linearGradient2690"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.128181,0,0,1.128181,-113.99314,-83.36009)"
x1="70.913956"
y1="101.74152"
x2="70.951942"
y2="88.923729" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="12.5"
x2="6.75"
y1="0.5"
x1="6.75"
id="linearGradient7035"
xlink:href="#linearGradient7029"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
r="9.3095722"
fy="431.19708"
fx="466.73566"
cy="431.19708"
cx="466.73566"
id="radialGradient6052"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient2438"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient24732"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
id="linearGradient17794">
<stop
id="stop17798"
offset="0"
style="stop-color:#f18383;stop-opacity:1;" />
<stop
style="stop-color:#ed6767;stop-opacity:1;"
offset="0.3807947"
id="stop8006" />
<stop
id="stop17796"
offset="1"
style="stop-color:#e62323;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient7029">
<stop
id="stop7031"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop7033"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3851"
id="linearGradient3857"
x1="35.599998"
y1="60.799999"
x2="27.200001"
y2="27.199999"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3823"
id="linearGradient1008"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.88885993,0,0,1.0394052,63.721122,-0.80985844)"
x1="23"
y1="34"
x2="15"
y2="-4" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3823"
id="linearGradient1010"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.76028301,0,0,1,49.15392,-0.23238375)"
x1="23"
y1="34"
x2="15"
y2="-4" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
inkscape:pageopacity="0.0000000"
inkscape:pageshadow="2"
inkscape:zoom="14.738757"
inkscape:cx="38.436077"
inkscape:cy="37.452276"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:grid-points="true"
fill="#555753"
showguides="false"
inkscape:guide-bbox="true"
guidetolerance="1px"
stroke="#555753"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="0"
inkscape:window-y="0"
showborder="true"
inkscape:showpageshadow="true"
borderlayer="true"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0"
inkscape:snap-global="true">
<sodipodi:guide
orientation="horizontal"
position="38.996647"
id="guide2194" />
<sodipodi:guide
orientation="horizontal"
position="9.0140845"
id="guide2196" />
<sodipodi:guide
orientation="vertical"
position="9.0140845"
id="guide2198" />
<sodipodi:guide
orientation="vertical"
position="38.975184"
id="guide2200" />
<sodipodi:guide
orientation="horizontal"
position="22.988281"
id="guide2202" />
<sodipodi:guide
orientation="vertical"
position="23.908786"
id="guide2204" />
<sodipodi:guide
orientation="vertical"
position="157.99417"
id="guide4332" />
<sodipodi:guide
orientation="horizontal"
position="-36.062446"
id="guide4334" />
<sodipodi:guide
orientation="horizontal"
position="-58.02695"
id="guide4336" />
<sodipodi:guide
orientation="vertical"
position="180.00287"
id="guide4338" />
<sodipodi:guide
orientation="vertical"
position="107.92217"
id="guide4417" />
<sodipodi:guide
orientation="vertical"
position="129.93087"
id="guide4419" />
<sodipodi:guide
orientation="horizontal"
position="19.996875"
id="guide5106" />
<sodipodi:guide
orientation="horizontal"
position="63.039674"
id="guide5119" />
<sodipodi:guide
orientation="horizontal"
position="49.066305"
id="guide5121" />
<sodipodi:guide
orientation="horizontal"
position="-86.007168"
id="guide5307" />
<sodipodi:guide
orientation="horizontal"
position="-108.09009"
id="guide5309" />
<sodipodi:guide
orientation="horizontal"
position="-100.15429"
id="guide3111" />
<inkscape:grid
id="GridFromPre046Settings"
type="xygrid"
originx="0px"
originy="0px"
spacingx="1px"
spacingy="1px"
color="#3f3fff"
empcolor="#3f3fff"
opacity="0.15"
empopacity="0.38"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata1312">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Lapo Calamandrei</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:subject>
<rdf:Bag>
<rdf:li>play</rdf:li>
<rdf:li>media</rdf:li>
<rdf:li>music</rdf:li>
<rdf:li>video</rdf:li>
<rdf:li>player</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:contributor>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="contorno"
style="display:inline"
transform="translate(0,16)" />
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
style="display:inline"
transform="translate(0,16)">
<path
style="fill:#8ae234;stroke:#172a04;stroke-width:1.74389;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 47.096415,44.766648 v -58 L 3,15.766648 Z"
id="path3035"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="display:inline;fill:url(#linearGradient1010);fill-opacity:1;stroke:#8ae234;stroke-width:1.74389;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 45.352505,41.535232 V -10 L 6.1403672,15.767616 Z"
id="path3035-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#172a04;fill-opacity:1;fill-rule:evenodd;stroke-width:1.00858"
id="rect394"
width="12.246909"
height="60"
x="-62.343266"
y="-14.233352"
ry="0"
inkscape:path-effect="#path-effect7179"
d="m -61.343266,-14.233352 10.24691,0 a 1,1 45 0 1 1,1 l 0,58 a 1,1 135 0 1 -1,1 h -10.24691 a 1,1 45 0 1 -1,-1 l 0,-58 a 1,1 135 0 1 1,-1 z"
sodipodi:type="rect"
transform="scale(-1,1)" />
<path
style="display:inline;fill:url(#linearGradient1008);fill-opacity:1;stroke:#8ae234;stroke-width:1.92239;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 59.77525,42.779313 V -11.26976 h -7.11088 v 54.049073 z"
id="path3035-3-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,432 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="64"
height="64"
id="svg1307"
sodipodi:version="0.32"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="media-playback-step.svg"
inkscape:export-filename="/home/lapo/Desktop/Grafica/Icone/media-actions-outlines.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1309">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect7179"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1"
unit="px"
method="auto"
mode="F"
radius="1"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<linearGradient
inkscape:collect="always"
id="linearGradient3851">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3853" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3855" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3823">
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="0"
id="stop3825" />
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="1"
id="stop3827" />
</linearGradient>
<linearGradient
id="linearGradient2684">
<stop
id="stop2686"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop2688"
offset="1"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2584">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2586" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2588" />
</linearGradient>
<linearGradient
id="linearGradient5075">
<stop
style="stop-color:#adb0a8;stop-opacity:1;"
offset="0"
id="stop5077" />
<stop
style="stop-color:#464744;stop-opacity:1"
offset="1"
id="stop5079" />
</linearGradient>
<linearGradient
id="linearGradient3340">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3342" />
<stop
style="stop-color:#ffffff;stop-opacity:0.62886596;"
offset="1"
id="stop3344" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5075"
id="linearGradient2306"
gradientUnits="userSpaceOnUse"
x1="71.288956"
y1="124.11652"
x2="70.826942"
y2="95"
gradientTransform="translate(-105.00042,-71.09425)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2684"
id="linearGradient2690"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.128181,0,0,1.128181,-113.99314,-83.36009)"
x1="70.913956"
y1="101.74152"
x2="70.951942"
y2="88.923729" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="12.5"
x2="6.75"
y1="0.5"
x1="6.75"
id="linearGradient7035"
xlink:href="#linearGradient7029"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
r="9.3095722"
fy="431.19708"
fx="466.73566"
cy="431.19708"
cx="466.73566"
id="radialGradient6052"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient2438"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
y2="424.95065"
x2="461.39169"
y1="436.79602"
x1="472.42236"
gradientUnits="userSpaceOnUse"
id="linearGradient24732"
xlink:href="#linearGradient17794"
inkscape:collect="always" />
<linearGradient
id="linearGradient17794">
<stop
id="stop17798"
offset="0"
style="stop-color:#f18383;stop-opacity:1;" />
<stop
style="stop-color:#ed6767;stop-opacity:1;"
offset="0.3807947"
id="stop8006" />
<stop
id="stop17796"
offset="1"
style="stop-color:#e62323;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient7029">
<stop
id="stop7031"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop7033"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3823"
id="linearGradient3829"
x1="23"
y1="34"
x2="15"
y2="-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.75,0,0,1,15.470323,9.6824872e-4)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3851"
id="linearGradient3857"
x1="35.599998"
y1="60.799999"
x2="27.200001"
y2="27.199999"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3823"
id="linearGradient18233"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8768379,0,0,1.0394052,1.1001462,-0.57650644)"
x1="23"
y1="34"
x2="15"
y2="-4" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
inkscape:pageopacity="0.0000000"
inkscape:pageshadow="2"
inkscape:zoom="10.421875"
inkscape:cx="32.191904"
inkscape:cy="32.047976"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:grid-points="true"
fill="#555753"
showguides="false"
inkscape:guide-bbox="true"
guidetolerance="1px"
stroke="#555753"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="2559"
inkscape:window-y="0"
showborder="true"
inkscape:showpageshadow="true"
borderlayer="true"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0"
inkscape:snap-global="false">
<sodipodi:guide
orientation="horizontal"
position="38.996647"
id="guide2194" />
<sodipodi:guide
orientation="horizontal"
position="9.0140845"
id="guide2196" />
<sodipodi:guide
orientation="vertical"
position="9.0140845"
id="guide2198" />
<sodipodi:guide
orientation="vertical"
position="38.975184"
id="guide2200" />
<sodipodi:guide
orientation="horizontal"
position="22.988281"
id="guide2202" />
<sodipodi:guide
orientation="vertical"
position="23.908786"
id="guide2204" />
<sodipodi:guide
orientation="vertical"
position="157.99417"
id="guide4332" />
<sodipodi:guide
orientation="horizontal"
position="-36.062446"
id="guide4334" />
<sodipodi:guide
orientation="horizontal"
position="-58.02695"
id="guide4336" />
<sodipodi:guide
orientation="vertical"
position="180.00287"
id="guide4338" />
<sodipodi:guide
orientation="vertical"
position="107.92217"
id="guide4417" />
<sodipodi:guide
orientation="vertical"
position="129.93087"
id="guide4419" />
<sodipodi:guide
orientation="horizontal"
position="19.996875"
id="guide5106" />
<sodipodi:guide
orientation="horizontal"
position="63.039674"
id="guide5119" />
<sodipodi:guide
orientation="horizontal"
position="49.066305"
id="guide5121" />
<sodipodi:guide
orientation="horizontal"
position="-86.007168"
id="guide5307" />
<sodipodi:guide
orientation="horizontal"
position="-108.09009"
id="guide5309" />
<sodipodi:guide
orientation="horizontal"
position="-100.15429"
id="guide3111" />
<inkscape:grid
id="GridFromPre046Settings"
type="xygrid"
originx="0px"
originy="0px"
spacingx="1px"
spacingy="1px"
color="#3f3fff"
empcolor="#3f3fff"
opacity="0.15"
empopacity="0.38"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata1312">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Lapo Calamandrei</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:subject>
<rdf:Bag>
<rdf:li>play</rdf:li>
<rdf:li>media</rdf:li>
<rdf:li>music</rdf:li>
<rdf:li>video</rdf:li>
<rdf:li>player</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:contributor>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="contorno"
style="display:inline"
transform="translate(0,16)" />
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
style="display:inline"
transform="translate(0,16)">
<path
style="fill:#8ae234;stroke:#172a04;stroke-width:1.73205;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 17.5,45 V -13 L 61,16 Z"
id="path3035"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="display:inline;fill:url(#linearGradient3829);fill-opacity:1;stroke:#8ae234;stroke-width:1.73205;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 19.220323,41.768584 V -9.766648 l 38.681784,25.767616 z"
id="path3035-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#172a04;fill-opacity:1;fill-rule:evenodd;stroke-width:1.00858"
id="rect394"
width="12.081266"
height="60"
x="2.4593668"
y="-14"
ry="0"
inkscape:path-effect="#path-effect7179"
d="M 3.4593668,-14 H 13.540633 a 1,1 45 0 1 1,1 l 0,58 a 1,1 135 0 1 -1,1 L 3.4593668,46 a 1,1 45 0 1 -1,-1 l 0,-58 a 1,1 135 0 1 1,-1 z"
sodipodi:type="rect" />
<path
style="display:inline;fill:url(#linearGradient18233);fill-opacity:1;stroke:#8ae234;stroke-width:1.90934;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 4.9926483,43.012665 V -11.036408 H 12.007352 V 43.012665 Z"
id="path3035-3-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -50,6 +50,9 @@
<file>button_valid.svg</file>
<file>button_invalid.svg</file>
<file>media-playback-start.svg</file>
<file>media-playback-start-back.svg</file>
<file>media-playback-step.svg</file>
<file>media-playback-step-back.svg</file>
<file>media-record.svg</file>
<file>media-playback-stop.svg</file>
<file>preferences-display.svg</file>

View File

@@ -33,6 +33,7 @@
#include "BomGroup.h"
#include "JointGroup.h"
#include "ViewGroup.h"
#include "SimulationGroup.h"
namespace Assembly
@@ -68,6 +69,7 @@ PyMOD_INIT_FUNC(AssemblyApp)
Assembly::BomGroup ::init();
Assembly::JointGroup ::init();
Assembly::ViewGroup ::init();
Assembly::SimulationGroup ::init();
PyMOD_Return(mod);
}

View File

@@ -13,7 +13,12 @@
<Author Licence="LGPL" Name="Ondsel" EMail="development@ondsel.com" />
<UserDocu>This class handles document objects in Assembly</UserDocu>
</Documentation>
<Attribute Name="Joints" ReadOnly="true">
<Documentation>
<UserDocu>A list of all joints this assembly link has.</UserDocu>
</Documentation>
<Parameter Name="Joints" Type="List"/>
</Attribute>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -45,3 +45,15 @@ int AssemblyLinkPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}
Py::List AssemblyLinkPy::getJoints() const
{
Py::List ret;
std::vector<App::DocumentObject*> list = getAssemblyLinkPtr()->getJoints();
for (auto It : list) {
ret.append(Py::Object(It->getPyObject(), true));
}
return ret;
}

View File

@@ -29,6 +29,9 @@
#include <unordered_map>
#endif
#include <thread>
#include <chrono>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObjectGroup.h>
@@ -67,10 +70,15 @@
#include <OndselSolver/ASMTRackPinionJoint.h>
#include <OndselSolver/ASMTRotationLimit.h>
#include <OndselSolver/ASMTTranslationLimit.h>
#include <OndselSolver/ASMTRotationalMotion.h>
#include <OndselSolver/ASMTTranslationalMotion.h>
#include <OndselSolver/ASMTGeneralMotion.h>
#include <OndselSolver/ASMTScrewJoint.h>
#include <OndselSolver/ASMTSphSphJoint.h>
#include <OndselSolver/ASMTTime.h>
#include <OndselSolver/ASMTConstantGravity.h>
#include <OndselSolver/ExternalSystem.h>
#include <OndselSolver/enum.h>
#include "AssemblyLink.h"
#include "AssemblyObject.h"
@@ -78,6 +86,7 @@
#include "AssemblyUtils.h"
#include "JointGroup.h"
#include "ViewGroup.h"
#include "SimulationGroup.h"
FC_LOG_LEVEL_INIT("Assembly", true, true, true)
@@ -110,7 +119,9 @@ PROPERTY_SOURCE(Assembly::AssemblyObject, App::Part)
AssemblyObject::AssemblyObject()
: mbdAssembly(std::make_shared<ASMTAssembly>())
, bundleFixed(false)
{}
{
mbdAssembly->externalSystem->freecadAssemblyObject = this;
}
AssemblyObject::~AssemblyObject() = default;
@@ -141,6 +152,7 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
mbdAssembly = makeMbdAssembly();
objectPartMap.clear();
motions.clear();
std::vector<App::DocumentObject*> groundedObjs = fixGroundedParts();
if (groundedObjs.empty()) {
@@ -159,7 +171,8 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
}
try {
mbdAssembly->runPreDrag(); // solve() is causing some issues with limits.
// mbdAssembly->runPreDrag(); // solve() is causing some issues with limits.
mbdAssembly->runKINEMATIC();
}
catch (const std::exception& e) {
FC_ERR("Solve failed: " << e.what());
@@ -177,6 +190,79 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
return 0;
}
int AssemblyObject::generateSimulation(App::DocumentObject* sim)
{
mbdAssembly = makeMbdAssembly();
objectPartMap.clear();
motions = getMotionsFromSimulation(sim);
std::vector<App::DocumentObject*> groundedObjs = fixGroundedParts();
if (groundedObjs.empty()) {
// If no part fixed we can't solve.
return -6;
}
std::vector<App::DocumentObject*> joints = getJoints();
removeUnconnectedJoints(joints, groundedObjs);
jointParts(joints);
create_mbdSimulationParameters(sim);
try {
mbdAssembly->runKINEMATIC();
}
catch (...) {
Base::Console().Error("Generation of simulation failed\n");
motions.clear();
return -1;
}
motions.clear();
return 0;
}
std::vector<App::DocumentObject*> AssemblyObject::getMotionsFromSimulation(App::DocumentObject* sim)
{
if (!sim) {
return {};
}
auto* prop = dynamic_cast<App::PropertyLinkList*>(sim->getPropertyByName("Group"));
if (!prop) {
return {};
}
return prop->getValue();
}
int Assembly::AssemblyObject::updateForFrame(size_t index, bool updateJCS)
{
if (!mbdAssembly) {
return -1;
}
auto nfrms = mbdAssembly->numberOfFrames();
if (index >= nfrms) {
return -1;
}
mbdAssembly->updateForFrame(index);
setNewPlacements();
auto jointDocs = getJoints(updateJCS);
redrawJointPlacements(jointDocs);
return 0;
}
size_t Assembly::AssemblyObject::numberOfFrames()
{
return mbdAssembly->numberOfFrames();
}
void AssemblyObject::preDrag(std::vector<App::DocumentObject*> dragParts)
{
bundleFixed = true;
@@ -480,6 +566,7 @@ void AssemblyObject::recomputeJointPlacements(std::vector<App::DocumentObject*>
std::shared_ptr<ASMTAssembly> AssemblyObject::makeMbdAssembly()
{
auto assembly = CREATE<ASMTAssembly>::With();
assembly->externalSystem->freecadAssemblyObject = this;
assembly->setName("OndselAssembly");
ParameterGrp::handle hPgr = App::GetApplication().GetParameterGroupByPath(
@@ -521,6 +608,23 @@ App::DocumentObject* AssemblyObject::getJointOfPartConnectingToGround(App::Docum
return nullptr;
}
template<typename T>
T* AssemblyObject::getGroup()
{
App::Document* doc = getDocument();
std::vector<DocumentObject*> groups = doc->getObjectsOfType(T::getClassTypeId());
if (groups.empty()) {
return nullptr;
}
for (auto group : groups) {
if (hasObject(group)) {
return dynamic_cast<T*>(group);
}
}
return nullptr;
}
JointGroup* AssemblyObject::getJointGroup() const
{
return Assembly::getJointGroup(this);
@@ -964,6 +1068,27 @@ void AssemblyObject::jointParts(std::vector<App::DocumentObject*> joints)
}
}
void Assembly::AssemblyObject::create_mbdSimulationParameters(App::DocumentObject* sim)
{
auto mbdSim = mbdAssembly->simulationParameters;
if (!sim) {
return;
}
auto valueOf = [](DocumentObject* docObj, const char* propName) {
auto* prop = dynamic_cast<App::PropertyFloat*>(docObj->getPropertyByName(propName));
if (!prop) {
return 0.0;
}
return prop->getValue();
};
mbdSim->settstart(valueOf(sim, "aTimeStart"));
mbdSim->settend(valueOf(sim, "bTimeEnd"));
mbdSim->sethout(valueOf(sim, "cTimeStepOutput"));
mbdSim->sethmin(1.0e-9);
mbdSim->sethmax(1.0);
mbdSim->seterrorTol(valueOf(sim, "fGlobalErrorTolerance"));
}
std::shared_ptr<ASMTJoint> AssemblyObject::makeMbdJointOfType(App::DocumentObject* joint,
JointType type)
{
@@ -1351,7 +1476,7 @@ AssemblyObject::makeMbdJoint(App::DocumentObject* joint)
if (maxEnabled) {
auto limit2 = ASMTRotationLimit::With();
limit2->setName(joint->getFullName() + "-LimiRotMax");
limit2->setName(joint->getFullName() + "-LimitRotMax");
limit2->setMarkerI(fullMarkerNameI);
limit2->setMarkerJ(fullMarkerNameJ);
limit2->settype("=<");
@@ -1361,6 +1486,90 @@ AssemblyObject::makeMbdJoint(App::DocumentObject* joint)
}
}
}
std::vector<App::DocumentObject*> done;
// Add motions if needed
for (auto* motion : motions) {
if (std::find(done.begin(), done.end(), motion) != done.end()) {
continue; // don't process twice (can happen in case of cylindrical)
}
auto* pJoint = dynamic_cast<App::PropertyXLinkSub*>(motion->getPropertyByName("Joint"));
if (!pJoint) {
continue;
}
App::DocumentObject* motionJoint = pJoint->getValue();
if (joint != motionJoint) {
continue;
}
auto* pType =
dynamic_cast<App::PropertyEnumeration*>(motion->getPropertyByName("MotionType"));
auto* pFormula = dynamic_cast<App::PropertyString*>(motion->getPropertyByName("Formula"));
if (!pType || !pFormula) {
continue;
}
std::string formula = pFormula->getValue();
if (formula == "") {
continue;
}
std::string motionType = pType->getValueAsString();
// check if there is a second motion as cylindrical can have both,
// in which case the solver needs a general motion.
for (auto* motion2 : motions) {
pJoint = dynamic_cast<App::PropertyXLinkSub*>(motion2->getPropertyByName("Joint"));
if (!pJoint) {
continue;
}
motionJoint = pJoint->getValue();
if (joint != motionJoint || motion2 == motion) {
continue;
}
auto* pType2 =
dynamic_cast<App::PropertyEnumeration*>(motion2->getPropertyByName("MotionType"));
auto* pFormula2 =
dynamic_cast<App::PropertyString*>(motion2->getPropertyByName("Formula"));
if (!pType2 || !pFormula2) {
continue;
}
std::string formula2 = pFormula2->getValue();
if (formula2 == "") {
continue;
}
std::string motionType2 = pType2->getValueAsString();
if (motionType2 == motionType) {
continue; // only if both motions are different. ie one angular and one linear.
}
auto ASMTmotion = CREATE<ASMTGeneralMotion>::With();
ASMTmotion->setName(joint->getFullName() + "-ScrewMotion");
ASMTmotion->setMarkerI(fullMarkerNameI);
ASMTmotion->setMarkerJ(fullMarkerNameJ);
ASMTmotion->rIJI->atiput(2, motionType == "Angular" ? formula2 : formula);
ASMTmotion->angIJJ->atiput(2, motionType == "Angular" ? formula : formula2);
mbdAssembly->addMotion(ASMTmotion);
done.push_back(motion2);
}
if (motionType == "Angular") {
auto ASMTmotion = CREATE<ASMTRotationalMotion>::With();
ASMTmotion->setName(joint->getFullName() + "-AngularMotion");
ASMTmotion->setMarkerI(fullMarkerNameI);
ASMTmotion->setMarkerJ(fullMarkerNameJ);
ASMTmotion->setRotationZ(formula);
mbdAssembly->addMotion(ASMTmotion);
}
else if (motionType == "Linear") {
auto ASMTmotion = CREATE<ASMTTranslationalMotion>::With();
ASMTmotion->setName(joint->getFullName() + "-LinearMotion");
ASMTmotion->setMarkerI(fullMarkerNameI);
ASMTmotion->setMarkerJ(fullMarkerNameJ);
ASMTmotion->setTranslationZ(formula);
mbdAssembly->addMotion(ASMTmotion);
}
}
return {mbdJoint};
}
@@ -1565,7 +1774,7 @@ AssemblyObject::MbDPartData AssemblyObject::getMbDData(App::DocumentObject* part
MbDPartData data = {mbdPart, Base::Placement()};
objectPartMap[part] = data; // Store the association
// Associate other objects conneted with fixed joints
// Associate other objects connected with fixed joints
if (bundleFixed) {
auto addConnectedFixedParts = [&](App::DocumentObject* currentPart, auto& self) -> void {
std::vector<App::DocumentObject*> joints = getJointsOfPart(currentPart);

View File

@@ -31,6 +31,9 @@
#include <App/FeaturePython.h>
#include <App/Part.h>
#include <App/PropertyLinks.h>
#include "SimulationGroup.h"
#include <3rdParty/OndselSolver/OndselSolver/enum.h>
namespace MbD
{
@@ -90,6 +93,9 @@ public:
and redraw the joints Args : enableRedo : This store initial positions to enable undo while
being in an active transaction (joint creation).*/
int solve(bool enableRedo = false, bool updateJCS = true);
int generateSimulation(App::DocumentObject* sim);
int updateForFrame(size_t index, bool updateJCS = true);
size_t numberOfFrames();
void preDrag(std::vector<App::DocumentObject*> dragParts);
void doDragStep();
void postDrag();
@@ -111,6 +117,7 @@ public:
// Ondsel Solver interface
std::shared_ptr<MbD::ASMTAssembly> makeMbdAssembly();
void create_mbdSimulationParameters(App::DocumentObject* sim);
std::shared_ptr<MbD::ASMTPart>
makeMbdPart(std::string& name, Base::Placement plc = Base::Placement(), double mass = 1.0);
std::shared_ptr<MbD::ASMTPart> getMbDPart(App::DocumentObject* obj);
@@ -140,6 +147,9 @@ public:
void jointParts(std::vector<App::DocumentObject*> joints);
JointGroup* getJointGroup() const;
ViewGroup* getExplodedViewGroup() const;
template<typename T>
T* getGroup();
std::vector<App::DocumentObject*>
getJoints(bool updateJCS = true, bool delBadJoints = false, bool subJoints = true);
std::vector<App::DocumentObject*> getGroundedJoints();
@@ -178,12 +188,15 @@ public:
std::vector<AssemblyLink*> getSubAssemblies();
void updateGroundedJointsPlacements();
std::vector<App::DocumentObject*> getMotionsFromSimulation(App::DocumentObject* sim);
private:
std::shared_ptr<MbD::ASMTAssembly> mbdAssembly;
std::unordered_map<App::DocumentObject*, MbDPartData> objectPartMap;
std::vector<std::pair<App::DocumentObject*, double>> objMasses;
std::vector<App::DocumentObject*> draggedParts;
std::vector<App::DocumentObject*> motions;
std::vector<std::pair<App::DocumentObject*, Base::Placement>> previousPositions;

View File

@@ -38,6 +38,52 @@
</UserDocu>
</Documentation>
</Methode>
<Methode Name="generateSimulation">
<Documentation>
<UserDocu>
Generate the simulation.
solve(simulationObject) -> int
Args:
simulationObject: The simulation Object.
Returns:
0 in case of success, otherwise the following codes in this order of
priority:
-6 if no parts are fixed.
-4 if over-constrained,
-3 if conflicting constraints,
-5 if malformed constraints
-1 if solver error,
-2 if redundant constraints.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="updateForFrame">
<Documentation>
<UserDocu>
Update entire assembly to frame number specified.
updateForFrame(index)
Args: index of frame.
Returns: None
</UserDocu>
</Documentation>
</Methode>
<Methode Name="numberOfFrames">
<Documentation>
<UserDocu>
numberOfFrames()
Args: None
Returns: Number of frames
</UserDocu>
</Documentation>
</Methode>
<Methode Name="undoSolve">
<Documentation>
<UserDocu>
@@ -125,7 +171,12 @@
</UserDocu>
</Documentation>
</Methode>
<Attribute Name="Joints" ReadOnly="true">
<Documentation>
<UserDocu>A list of all joints this assembly has.</UserDocu>
</Documentation>
<Parameter Name="Joints" Type="List"/>
</Attribute>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -68,6 +68,18 @@ PyObject* AssemblyObjectPy::solve(PyObject* args)
return Py_BuildValue("i", ret);
}
PyObject* AssemblyObjectPy::generateSimulation(PyObject* args)
{
PyObject* pyobj;
if (!PyArg_ParseTuple(args, "O", &pyobj)) {
return nullptr;
}
auto* obj = static_cast<App::DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
int ret = this->getAssemblyObjectPtr()->generateSimulation(obj);
return Py_BuildValue("i", ret);
}
PyObject* AssemblyObjectPy::ensureIdentityPlacements(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
@@ -77,6 +89,31 @@ PyObject* AssemblyObjectPy::ensureIdentityPlacements(PyObject* args)
Py_Return;
}
PyObject* AssemblyObjectPy::updateForFrame(PyObject* args)
{
unsigned long index {};
if (!PyArg_ParseTuple(args, "k", &index)) {
throw Py::RuntimeError("updateForFrame requires an integer index");
}
PY_TRY
{
this->getAssemblyObjectPtr()->updateForFrame(index);
}
PY_CATCH;
Py_Return;
}
PyObject* AssemblyObjectPy::numberOfFrames(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
size_t ret = this->getAssemblyObjectPtr()->numberOfFrames();
return Py_BuildValue("k", ret);
}
PyObject* AssemblyObjectPy::undoSolve(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
@@ -151,3 +188,15 @@ PyObject* AssemblyObjectPy::exportAsASMT(PyObject* args)
Py_Return;
}
Py::List AssemblyObjectPy::getJoints() const
{
Py::List ret;
std::vector<App::DocumentObject*> list = getAssemblyObjectPtr()->getJoints();
for (auto It : list) {
ret.append(Py::Object(It->getPyObject(), true));
}
return ret;
}

View File

@@ -28,6 +28,7 @@ generate_from_xml(BomObjectPy)
generate_from_xml(BomGroupPy)
generate_from_xml(JointGroupPy)
generate_from_xml(ViewGroupPy)
generate_from_xml(SimulationGroupPy)
SET(Python_SRCS
AssemblyObjectPy.xml
@@ -42,6 +43,8 @@ SET(Python_SRCS
JointGroupPyImp.cpp
ViewGroupPy.xml
ViewGroupPyImp.cpp
SimulationGroupPy.xml
SimulationGroupPyImp.cpp
)
SOURCE_GROUP("Python" FILES ${Python_SRCS})
@@ -68,6 +71,8 @@ SET(Assembly_SRCS
JointGroup.h
ViewGroup.cpp
ViewGroup.h
SimulationGroup.cpp
SimulationGroup.h
${Module_SRCS}
${Python_SRCS}
)

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 Ondsel <development@ondsel.com> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <App/Application.h>
#include <App/Document.h>
#include <App/FeaturePythonPyImp.h>
#include <App/PropertyPythonObject.h>
#include <Base/Console.h>
#include <Base/Tools.h>
#include "SimulationGroup.h"
#include "SimulationGroupPy.h"
using namespace Assembly;
PROPERTY_SOURCE(Assembly::SimulationGroup, App::DocumentObjectGroup)
SimulationGroup::SimulationGroup()
{}
SimulationGroup::~SimulationGroup() = default;
PyObject* SimulationGroup::getPyObject()
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new SimulationGroupPy(this), true);
}
return Py::new_reference_to(PythonObject);
}

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 Ondsel <development@ondsel.com> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef ASSEMBLY_SimulationGroup_H
#define ASSEMBLY_SimulationGroup_H
#include <Mod/Assembly/AssemblyGlobal.h>
#include <App/DocumentObjectGroup.h>
#include <App/PropertyLinks.h>
namespace Assembly
{
class AssemblyExport SimulationGroup: public App::DocumentObjectGroup
{
PROPERTY_HEADER_WITH_OVERRIDE(Assembly::SimulationGroup);
public:
SimulationGroup();
~SimulationGroup() override;
PyObject* getPyObject() override;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override
{
return "AssemblyGui::ViewProviderSimulationGroup";
}
};
} // namespace Assembly
#endif // ASSEMBLY_SimulationGroup_H

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="DocumentObjectGroupPy"
Name="SimulationGroupPy"
Twin="SimulationGroup"
TwinPointer="SimulationGroup"
Include="Mod/Assembly/App/SimulationGroup.h"
Namespace="Assembly"
FatherInclude="App/DocumentObjectGroupPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="Ondsel" EMail="development@ondsel.com" />
<UserDocu>This class is a group subclass for joints.</UserDocu>
</Documentation>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,47 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 Ondsel <development@ondsel.com> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
// inclusion of the generated files (generated out of SimulationGroup.xml)
#include "SimulationGroupPy.h"
#include "SimulationGroupPy.cpp"
using namespace Assembly;
// returns a string which represents the object e.g. when printed in python
std::string SimulationGroupPy::representation() const
{
return {"<Simulation Group>"};
}
PyObject* SimulationGroupPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int SimulationGroupPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -13,6 +13,7 @@ set(Assembly_Scripts
CommandSolveAssembly.py
CommandCreateJoint.py
CommandCreateView.py
CommandCreateSimulation.py
CommandExportASMT.py
TestAssemblyWorkbench.py
JointObject.py

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,7 @@
#include "ViewProviderBomGroup.h"
#include "ViewProviderJointGroup.h"
#include "ViewProviderViewGroup.h"
#include "ViewProviderSimulationGroup.h"
namespace AssemblyGui
@@ -66,6 +67,7 @@ PyMOD_INIT_FUNC(AssemblyGui)
AssemblyGui::ViewProviderBomGroup::init();
AssemblyGui::ViewProviderJointGroup::init();
AssemblyGui::ViewProviderViewGroup::init();
AssemblyGui::ViewProviderSimulationGroup::init();
PyMOD_Return(mod);
}

View File

@@ -28,6 +28,15 @@ SOURCE_GROUP("Resources" FILES ${AssemblyResource_SRCS})
generate_from_xml(ViewProviderAssemblyPy)
set(AssemblyGui_UIC_SRCS
TaskAssemblyCreateBom.ui
TaskAssemblyCreateJoint.ui
TaskAssemblyCreateSimulation.ui
TaskAssemblyCreateView.ui
TaskAssemblyInsertLink.ui
Assembly.ui
)
SET(Python_SRCS
ViewProviderAssemblyPy.xml
ViewProviderAssemblyPyImp.cpp
@@ -51,6 +60,8 @@ SET(AssemblyGui_SRCS_Module
ViewProviderJointGroup.h
ViewProviderViewGroup.cpp
ViewProviderViewGroup.h
ViewProviderSimulationGroup.cpp
ViewProviderSimulationGroup.h
${Assembly_QRC_SRCS}
)

View File

@@ -26,10 +26,13 @@
<file>icons/Assembly_JointGroup.svg</file>
<file>icons/Assembly_ExplodedView.svg</file>
<file>icons/Assembly_ExplodedViewGroup.svg</file>
<file>icons/Assembly_CreateSimulation.svg</file>
<file>icons/Assembly_SimulationGroup.svg</file>
<file>panels/TaskAssemblyCreateBom.ui</file>
<file>panels/TaskAssemblyCreateJoint.ui</file>
<file>panels/TaskAssemblyInsertLink.ui</file>
<file>panels/TaskAssemblyCreateView.ui</file>
<file>panels/TaskAssemblyCreateSimulation.ui</file>
<file>preferences/Assembly.ui</file>
<file>icons/Assembly_CreateJointDistance.svg</file>
<file>icons/AssemblyWorkbench.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -0,0 +1,339 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskAssemblyCreateSimulation</class>
<widget class="QDialog" name="TaskAssemblyCreateSimulation">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>602</height>
</rect>
</property>
<property name="windowTitle">
<string>Create Simulation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_motions">
<property name="title">
<string>Motions</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QListWidget" name="motionList">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>75</height>
</size>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="motion_buttonsLayout">
<item>
<widget class="QToolButton" name="AddButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Add a prescribed motion</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/list-add.svg</normaloff>:/icons/list-add.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="RemoveButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Delete selected motions</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/edit-delete.svg</normaloff>:/icons/edit-delete.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_settings">
<property name="title">
<string>Simulation settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="TimeStartLabel">
<property name="text">
<string>Start</string>
</property>
<property name="toolTip">
<string>Start time of the simulation</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="TimeStartSpinBox">
<property name="toolTip">
<string>Start time of the simulation</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="TimeEndLabel">
<property name="text">
<string>End</string>
</property>
<property name="toolTip">
<string>End time of the simulation</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="TimeEndSpinBox">
<property name="toolTip">
<string>End time of the simulation</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="TimeStepOutputLabel">
<property name="text">
<string>Step</string>
</property>
<property name="toolTip">
<string>Time Step</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="TimeStepOutputSpinBox">
<property name="toolTip">
<string>Time Step</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="GlobalErrorToleranceLabel">
<property name="text">
<string>Tolerance</string>
</property>
<property name="toolTip">
<string>Global Error Tolerance</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="GlobalErrorToleranceSpinBox">
<property name="toolTip">
<string>Global Error Tolerance</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="RunKinematicsButton">
<property name="text">
<string>Generate</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_player">
<property name="title">
<string>Animation player</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="FrameLabel">
<property name="text">
<string>Frame</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="frameSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="FrameTimeLabel">
<property name="text">
<string>0.00 s</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="fps_layout">
<item>
<widget class="QLabel" name="FramesPerSecondLabel">
<property name="text">
<string>Frames Per Second</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="FramesPerSecondSpinBox"/>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="controls_layout">
<item>
<widget class="QToolButton" name="StepBackwardButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Step backward</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/media-playback-step-back.svg</normaloff>:/icons/media-playback-step-back.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="PlayBackwardButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Play backward</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/media-playback-start-back.svg</normaloff>:/icons/media-playback-start-back.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="StopButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Stop</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/media-playback-stop.svg</normaloff>:/icons/media-playback-stop.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="PlayForwardButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Play forward</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/media-playback-start.svg</normaloff>:/icons/media-playback-start.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="StepForwardButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Step forward</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="Icons/resource.qrc">
<normaloff>:/icons/media-playback-step.svg</normaloff>:/icons/media-playback-step.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 Ondsel <development@ondsel.com> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include "ViewProviderSimulationGroup.h"
using namespace AssemblyGui;
PROPERTY_SOURCE(AssemblyGui::ViewProviderSimulationGroup, Gui::ViewProviderDocumentObjectGroup)
ViewProviderSimulationGroup::ViewProviderSimulationGroup()
{}
ViewProviderSimulationGroup::~ViewProviderSimulationGroup() = default;
QIcon ViewProviderSimulationGroup::getIcon() const
{
return Gui::BitmapFactory().pixmap("Assembly_SimulationGroup.svg");
}

View File

@@ -0,0 +1,63 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 Ondsel <development@ondsel.com> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef ASSEMBLYGUI_VIEWPROVIDER_ViewProviderSimulationGroup_H
#define ASSEMBLYGUI_VIEWPROVIDER_ViewProviderSimulationGroup_H
#include <Mod/Assembly/AssemblyGlobal.h>
#include <Gui/ViewProviderDocumentObjectGroup.h>
namespace AssemblyGui
{
class AssemblyGuiExport ViewProviderSimulationGroup: public Gui::ViewProviderDocumentObjectGroup
{
PROPERTY_HEADER_WITH_OVERRIDE(AssemblyGui::ViewProviderSimulationGroup);
public:
ViewProviderSimulationGroup();
~ViewProviderSimulationGroup() override;
/// deliver the icon shown in the tree view. Override from ViewProvider.h
QIcon getIcon() const override;
// Prevent dragging of the joints and dropping things inside the joint group.
bool canDragObjects() const override
{
return false;
};
bool canDropObjects() const override
{
return false;
};
bool canDragAndDropObject(App::DocumentObject*) const override
{
return false;
};
};
} // namespace AssemblyGui
#endif // ASSEMBLYGUI_VIEWPROVIDER_ViewProviderSimulationGroup_H

View File

@@ -63,7 +63,7 @@ class AssemblyWorkbench(Workbench):
# load the builtin modules
from PySide import QtCore, QtGui
from PySide.QtCore import QT_TRANSLATE_NOOP
import CommandCreateAssembly, CommandInsertLink, CommandInsertNewPart, CommandCreateJoint, CommandSolveAssembly, CommandExportASMT, CommandCreateView, CommandCreateBom
import CommandCreateAssembly, CommandInsertLink, CommandInsertNewPart, CommandCreateJoint, CommandSolveAssembly, CommandExportASMT, CommandCreateView, CommandCreateSimulation, CommandCreateBom
import Preferences
FreeCADGui.addLanguagePath(":/translations")
@@ -79,6 +79,7 @@ class AssemblyWorkbench(Workbench):
"Assembly_Insert",
"Assembly_SolveAssembly",
"Assembly_CreateView",
"Assembly_CreateSimulation",
"Assembly_CreateBom",
]

View File

@@ -80,18 +80,44 @@ def isDocTemporary(doc):
def assembly_has_at_least_n_parts(n):
assembly = activeAssembly()
i = 0
if not assembly:
assembly = activePart()
if not assembly:
return False
for obj in assembly.OutList:
# note : groundedJoints comes in the outlist so we filter those out.
if hasattr(obj, "Placement") and not hasattr(obj, "ObjectToGround"):
i = i + 1
if i == n:
return True
return False
i = number_of_components_in(assembly)
return i >= n
def number_of_components_in(assembly):
if not assembly:
return 0
i = 0
for obj in assembly.Group:
if isLinkGroup(obj):
i = i + obj.ElementCount
continue
if obj.isDerivedFrom("Assembly::AssemblyObject") or obj.isDerivedFrom(
"Assembly::AssemblyLink"
):
i = i + number_of_components_in(obj)
continue
if obj.isDerivedFrom("App::Link"):
obj = obj.getLinkedObject()
if not obj.isDerivedFrom("App::GeoFeature"):
continue
# if obj.isDerivedFrom("App::DatumElement") or obj.isDerivedFrom("App::LocalCoordinateSystem"):
if obj.isDerivedFrom("App::Origin"):
# after https://github.com/FreeCAD/FreeCAD/pull/16675 merges,
# replace the App::Origin test by the one above
continue
i = i + 1
return i
def isLink(obj):
@@ -546,6 +572,20 @@ def color_from_unsigned(c):
]
def getJointsOfType(asm, jointTypes):
if not (
asm.isDerivedFrom("Assembly::AssemblyObject") or asm.isDerivedFrom("Assembly::AssemblyLink")
):
return []
joints = []
allJoints = asm.Joints
for joint in allJoints:
if joint.JointType in jointTypes:
joints.append(joint)
return joints
def getBomGroup(assembly):
bom_group = None
@@ -588,6 +628,20 @@ def getViewGroup(assembly):
return view_group
def getSimulationGroup(assembly):
sim_group = None
for obj in assembly.OutList:
if obj.TypeId == "Assembly::SimulationGroup":
sim_group = obj
break
if not sim_group:
sim_group = assembly.newObject("Assembly::SimulationGroup", "Simulations")
return sim_group
def isAssemblyGrounded():
assembly = activeAssembly()
if not assembly: