Compare commits

...

41 Commits

Author SHA1 Message Date
DeepSOIC
50f4372b02 Resample: re-implement, + reference placement support
Now uses ValueSeriesGenerator for extra flexibility
2018-09-07 17:40:32 +03:00
DeepSOIC
af75a3a0f0 fixup 2018-09-07 16:38:21 +03:00
DeepSOIC
f874b338e7 fixup 2018-09-07 16:18:14 +03:00
DeepSOIC
e18a270636 ProjectArray: reference placement support 2018-09-07 16:05:14 +03:00
DeepSOIC
dfa4377013 PopulateCopies: change command logic
collapse into one command
2018-09-07 02:48:07 +03:00
DeepSOIC
0224b6f98a JoinArrays: improve reference placement support 2018-09-07 01:18:56 +03:00
DeepSOIC
f7bbd41b2c BaseFeature: add dereferencing to getPlacementsList 2018-09-07 01:18:02 +03:00
DeepSOIC
e4c342f5ba BaseFeature: fix reference marker sometimes show up on non-placement results 2018-09-07 00:24:08 +03:00
DeepSOIC
b8d3df590c BaseFeature: fix readonlyness 2018-09-07 00:17:43 +03:00
DeepSOIC
56c39bd493 ArrayFilter: fix reference placement support 2018-09-06 23:38:30 +03:00
DeepSOIC
870ef63088 ReferencePlacement: refactor CS 2018-09-06 23:38:00 +03:00
DeepSOIC
a192e19209 BaseFeature: improve attacher disabling 2018-09-06 01:33:56 +03:00
DeepSOIC
7d2d62bdea BaseFeature: add updateReadonlyness global method
+ make basic Lattice properties such as MarkerSize hidden on objects with shape results.
2018-09-06 01:33:56 +03:00
DeepSOIC
32e840a941 AttachableArray, LinearArray, PolarArray: add 'external' reference option 2018-09-06 01:33:56 +03:00
DeepSOIC
d8a3293dbc ReferencePlacement: fix viewprovider update when setting refplm to None 2018-09-06 01:33:56 +03:00
DeepSOIC
64879965ba ReferencePlacement: add reference placement link 2018-09-06 01:33:56 +03:00
DeepSOIC
3a2662685e AttachedPlacement: subsequence-array reference placement support 2018-09-06 01:33:56 +03:00
DeepSOIC
22925c8187 BaseFeature: add assureProperties method 2018-09-06 01:33:56 +03:00
DeepSOIC
c3bb345c3f AttachedPlacement: subsequence-array an attached array support
now, one can "array an attached placement" a polar array.
2018-09-06 01:33:55 +03:00
DeepSOIC
7331c60ce5 ReferencePlacement: all arrays have reference placement 2018-09-06 01:33:55 +03:00
DeepSOIC
340c51b108 ReferencePlacement: workaround for FC bug 3564
https://freecadweb.org/tracker/view.php?id=3564
2018-09-06 01:33:55 +03:00
DeepSOIC
c566979574 fix refplm visibility after restore 2018-09-06 01:33:55 +03:00
DeepSOIC
a80c075b4a JoinArrays: reference placement support 2018-09-06 01:33:55 +03:00
DeepSOIC
8cb8ab7bd9 ReferencePlacement: fix expose placement 2018-09-06 01:33:55 +03:00
DeepSOIC
1e4416dd9f ArrayFilter: reference placement support 2018-09-06 01:33:55 +03:00
DeepSOIC
fb031132e3 ArrayFilter: fix 2018-09-06 01:33:55 +03:00
DeepSOIC
5a72dedd4c Invert: clean up imports 2018-09-06 01:33:55 +03:00
DeepSOIC
8f15765047 PolarArray: 'center' reference option 2018-09-06 01:33:55 +03:00
DeepSOIC
65c6dad39f Invert: support for reference placement 2018-09-06 01:33:55 +03:00
DeepSOIC
9d2043f546 ReferencePlacement: add missing tetra-marker 2018-09-06 01:33:55 +03:00
DeepSOIC
7d0d5d63a3 PopulateChildren: reference inheritance 2018-09-06 01:33:55 +03:00
DeepSOIC
618bbc331f LinearArray: fix 2018-09-06 01:33:55 +03:00
DeepSOIC
bd3ac15fd2 fixup for icons 2018-09-06 01:33:55 +03:00
DeepSOIC
681c7330ba LinearArray: reference placement support 2018-09-06 01:33:55 +03:00
DeepSOIC
c97e733c6a Populate tools: icons 2018-09-06 01:33:55 +03:00
DeepSOIC
eecd808a22 ReferencePlacement: tweak
increase refplm marker a bit, to make it more visible
2018-09-06 01:33:55 +03:00
DeepSOIC
62c6b6d7cc PopulateCopies: Reference placement propagation 2018-09-06 01:33:55 +03:00
DeepSOIC
f4b88d1a2e ReferencePlacement: fixes 2018-09-06 01:33:55 +03:00
DeepSOIC
6c620b130f ReferencePlacement: show on screen
initial implementation. to be improved...
2018-09-06 01:33:55 +03:00
DeepSOIC
9449dd9352 fixup
fix basefeature source function
2018-09-06 01:33:55 +03:00
DeepSOIC
c7dd44868e ReferencePlacement: the very basics
* ref plm support in polar array
* referencing options for populate features
2018-09-06 01:33:55 +03:00
29 changed files with 3095 additions and 272 deletions

View File

@ -63,7 +63,7 @@ class Lattice2Workbench (Workbench):
+ Lattice2.ArrayFeatures.JoinArrays.exportedCommands + Lattice2.ArrayFeatures.JoinArrays.exportedCommands
+ Lattice2.ArrayFeatures.ArrayFilter.exportedCommands + Lattice2.ArrayFeatures.ArrayFilter.exportedCommands
+ Lattice2.ArrayFeatures.ProjectArray.exportedCommands + Lattice2.ArrayFeatures.ProjectArray.exportedCommands
+ Lattice2.ArrayFeatures.Resample.exportedCommands + Lattice2.ArrayFeatures.Resample2.exportedCommands
+ Lattice2.ArrayFeatures.PopulateCopies.exportedCommands + Lattice2.ArrayFeatures.PopulateCopies.exportedCommands
+ Lattice2.ArrayFeatures.PopulateChildren.exportedCommands + Lattice2.ArrayFeatures.PopulateChildren.exportedCommands
+ Lattice2.ArrayFeatures.Mirror.exportedCommands + Lattice2.ArrayFeatures.Mirror.exportedCommands

View File

@ -12,4 +12,5 @@ import lattice2PopulateChildren as PopulateChildren
import lattice2PopulateCopies as PopulateCopies import lattice2PopulateCopies as PopulateCopies
import lattice2ProjectArray as ProjectArray import lattice2ProjectArray as ProjectArray
import lattice2Resample as Resample import lattice2Resample as Resample
import lattice2Resample2 as Resample2
import lattice2Mirror as Mirror import lattice2Mirror as Mirror

View File

@ -8,4 +8,5 @@ import lattice2Markers as Markers
import lattice2ValueSeriesGenerator as ValueSeriesGenerator import lattice2ValueSeriesGenerator as ValueSeriesGenerator
import lattice2ShapeCopy as ShapeCopy import lattice2ShapeCopy as ShapeCopy
import lattice2Subsequencer as Subsequencer import lattice2Subsequencer as Subsequencer
import lattice2Utils as Utils import lattice2Utils as Utils
import lattice2CoinGlue as CoinGlue

View File

@ -34,15 +34,19 @@
<file>icons/Lattice2_PopulateChildren_Array.svg</file> <file>icons/Lattice2_PopulateChildren_Array.svg</file>
<file>icons/Lattice2_PopulateChildren_Move.svg</file> <file>icons/Lattice2_PopulateChildren_Move.svg</file>
<file>icons/Lattice2_PopulateChildren_Normal.svg</file> <file>icons/Lattice2_PopulateChildren_Normal.svg</file>
<file>icons/Lattice2_PopulateChildren_Ref.svg</file>
<file>icons/Lattice2_PopulateChildren_Plms_Array.svg</file> <file>icons/Lattice2_PopulateChildren_Plms_Array.svg</file>
<file>icons/Lattice2_PopulateChildren_Plms_Normal.svg</file> <file>icons/Lattice2_PopulateChildren_Plms_Normal.svg</file>
<file>icons/Lattice2_PopulateChildren_Plms_Move.svg</file> <file>icons/Lattice2_PopulateChildren_Plms_Move.svg</file>
<file>icons/Lattice2_PopulateChildren_Plms_Ref.svg</file>
<file>icons/Lattice2_PopulateCopies_Array.svg</file> <file>icons/Lattice2_PopulateCopies_Array.svg</file>
<file>icons/Lattice2_PopulateCopies_Move.svg</file> <file>icons/Lattice2_PopulateCopies_Move.svg</file>
<file>icons/Lattice2_PopulateCopies_Normal.svg</file> <file>icons/Lattice2_PopulateCopies_Normal.svg</file>
<file>icons/Lattice2_PopulateCopies_Ref.svg</file>
<file>icons/Lattice2_PopulateCopies_Plms_Array.svg</file> <file>icons/Lattice2_PopulateCopies_Plms_Array.svg</file>
<file>icons/Lattice2_PopulateCopies_Plms_Normal.svg</file> <file>icons/Lattice2_PopulateCopies_Plms_Normal.svg</file>
<file>icons/Lattice2_PopulateCopies_Plms_Move.svg</file> <file>icons/Lattice2_PopulateCopies_Plms_Move.svg</file>
<file>icons/Lattice2_PopulateCopies_Plms_Ref.svg</file>
<file>icons/Lattice2_ProjectArray.svg</file> <file>icons/Lattice2_ProjectArray.svg</file>
<file>icons/Lattice2_RecomputeLocker_ForceRecompute.svg</file> <file>icons/Lattice2_RecomputeLocker_ForceRecompute.svg</file>
<file>icons/Lattice2_RecomputeLocker_Locked.svg</file> <file>icons/Lattice2_RecomputeLocker_Locked.svg</file>

View File

@ -0,0 +1,448 @@
<?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="svg2568"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Lattice2_PopulateChildren_Plms_Move.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/Part/mystuff/Part_Compound_5_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2570">
<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="perspective2576" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3023">
<stop
id="stop3025"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3027"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3030">
<stop
id="stop3032"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3034"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3837"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3839"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3841"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3804"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3806"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3808"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3804-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<linearGradient
id="linearGradient3377-5">
<stop
id="stop3379-4"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381-8"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3806-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<linearGradient
id="linearGradient3080">
<stop
id="stop3082"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3084"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3808-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<linearGradient
id="linearGradient3087">
<stop
id="stop3089"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3091"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4368"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4370"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.4172297"
inkscape:cx="41.893894"
inkscape:cy="31.769057"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:object-nodes="true"
inkscape:snap-global="false"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata2573">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3794"
transform="matrix(0.66209119,0,0,0.66209119,16.510051,9.6145811)">
<path
inkscape:connector-curvature="0"
id="path3018"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
id="g3049"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.77833186,0,0,0.71925582,-2.7462371,5.126137)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3045"
d="m 10.351377,24.493827 -5.6980057,0 0,25.925926 5.6980057,0"
style="fill:none;stroke:#000000;stroke-width:2.67304277;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<use
height="64"
width="64"
transform="matrix(-1,0,0,1,47.081698,0)"
id="use3047"
xlink:href="#path3045"
y="0"
x="0"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3823"
sodipodi:cx="53.466286"
sodipodi:cy="26.488129"
sodipodi:rx="7.5973411"
sodipodi:ry="7.5973411"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
transform="translate(-1.0080847,-16.969427)" />
<path
style="fill:none;stroke:#000000;stroke-width:1.49999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.365217,54.049894 18.817583,0 0,-36.737441"
id="path3866"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 32.813497,9.2273923 12.494629,0"
id="path3868"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 60.821116,9.5634205 7.392622,0"
id="path3868-3"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path3888"
sodipodi:cx="51.748352"
sodipodi:cy="14.099802"
sodipodi:rx="2.3521979"
sodipodi:ry="2.3521979"
d="m 54.10055,14.099802 a 2.3521979,2.3521979 0 1 1 -4.704396,0 2.3521979,2.3521979 0 1 1 4.704396,0 z"
transform="translate(0.84007066,-4.5363816)" />
<path
transform="translate(-0.88928087,5.3103559)"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
sodipodi:ry="7.5973411"
sodipodi:rx="7.5973411"
sodipodi:cy="26.488129"
sodipodi:cx="53.466286"
id="path4352"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 48.072426,31.793994 9.072763,0"
id="path4358"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 32.730167,31.744784 11.756572,0"
id="path4376"
inkscape:connector-curvature="0" />
<g
id="g3794-9"
transform="matrix(0.66209119,0,0,0.66209119,16.746967,-12.543942)">
<path
inkscape:connector-curvature="0"
id="path3018-4"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020-5"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022-5"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024-4"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<use
x="0"
y="0"
xlink:href="#g3049"
id="use3040"
width="64"
height="64"
transform="translate(0.11880393,-21.6427)" />
<g
transform="matrix(0.66209119,0,0,0.66209119,16.586547,31.892723)"
id="use4372">
<path
style="fill:none;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
id="path3042"
inkscape:connector-curvature="0" />
<path
style="fill:#1798ff;fill-opacity:0.50210972;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
id="path3044"
inkscape:connector-curvature="0" />
<path
style="fill:#006eca;fill-opacity:0.50196078;stroke:#1798ff;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.50196078"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
id="path3046"
inkscape:connector-curvature="0" />
<path
style="fill:#0065b7;fill-opacity:0.63291141;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
id="path3048"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,461 @@
<?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="svg2568"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Lattice2_PopulateChildren_Move.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/Part/mystuff/Part_Compound_5_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2570">
<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="perspective2576" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3023">
<stop
id="stop3025"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3027"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3030">
<stop
id="stop3032"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3034"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3837"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3839"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3841"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3804"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3806"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3808"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3804-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<linearGradient
id="linearGradient3377-5">
<stop
id="stop3379-4"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381-8"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3806-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<linearGradient
id="linearGradient3080">
<stop
id="stop3082"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3084"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3808-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<linearGradient
id="linearGradient3087">
<stop
id="stop3089"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3091"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4368"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4370"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.9518802"
inkscape:cx="39.412699"
inkscape:cy="28.156141"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:object-nodes="true"
inkscape:snap-global="false"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata2573">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3794"
transform="matrix(0.66209119,0,0,0.66209119,16.9445,9.1766352)">
<path
inkscape:connector-curvature="0"
id="path3018"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
id="g3049"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.77833186,0,0,0.61958115,-2.2218112,8.2680831)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3045"
d="m 10.351377,24.493827 -5.6980057,0 0,25.925926 5.6980057,0"
style="fill:none;stroke:#000000;stroke-width:2.88003969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<use
height="64"
width="64"
transform="matrix(-1,0,0,1,47.081698,0)"
id="use3047"
xlink:href="#path3045"
y="0"
x="0"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3823"
sodipodi:cx="53.466286"
sodipodi:cy="26.488129"
sodipodi:rx="7.5973411"
sodipodi:ry="7.5973411"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
transform="translate(-1.0080847,-16.969427)" />
<g
id="g3798"
transform="matrix(0.94897349,0,0,0.94897349,-24.695619,-10.087879)">
<g
id="g3843"
transform="matrix(0.57659255,0,0,0.32499812,79.277735,9.6499853)">
<path
style="fill:url(#radialGradient4366);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -65.878042,4.7970936 -12.866966,10.1036774 21.744289,5.108296 0.30338,44.045609 11.486763,-13.03934 0.410614,-42.3363302 z"
id="path3845"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient4368);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -78.552461,15.155385 21.896364,4.143912 0,44.912523 -22.192265,-6.236008 0.295901,-42.820427 z"
id="path3847"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient4370);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M -56.822875,19.354658 -44.896728,9.001326"
id="path3849"
inkscape:connector-curvature="0" />
</g>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1.49999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.602825,52.743051 18.817583,0 0,-35.787009"
id="path3866"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 34.261979,9.2273923 11.114739,0"
id="path3868"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 60.821116,9.5634205 7.392622,0"
id="path3868-3"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path3888"
sodipodi:cx="51.748352"
sodipodi:cy="14.099802"
sodipodi:rx="2.3521979"
sodipodi:ry="2.3521979"
d="m 54.10055,14.099802 a 2.3521979,2.3521979 0 1 1 -4.704396,0 2.3521979,2.3521979 0 1 1 4.704396,0 z"
transform="translate(0.84007066,-4.5363816)" />
<path
transform="translate(-1.0080848,3.5282969)"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
sodipodi:ry="7.5973411"
sodipodi:rx="7.5973411"
sodipodi:cy="26.488129"
sodipodi:cx="53.466286"
id="path4352"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 47.716014,29.893131 9.072763,0"
id="path4358"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.266798,29.725117 10.920919,0"
id="path4376"
inkscape:connector-curvature="0" />
<g
transform="matrix(0.81161259,0,0,0.63682405,-2.3339197,-14.471639)"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
id="g3040">
<path
style="fill:none;stroke:#000000;stroke-width:2.78192782;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 10.351377,24.493827 -5.6980057,0 0,25.925926 5.6980057,0"
id="path3042"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<use
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
x="0"
y="0"
xlink:href="#path3045"
id="use3044"
transform="matrix(-1,0,0,1,47.081698,0)"
width="64"
height="64" />
</g>
<g
transform="matrix(0.66209119,0,0,0.66209119,16.81656,31.029372)"
id="use4372">
<path
style="fill:none;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
id="path3042-7"
inkscape:connector-curvature="0" />
<path
style="fill:#1798ff;fill-opacity:0.50210972;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
id="path3044"
inkscape:connector-curvature="0" />
<path
style="fill:#006eca;fill-opacity:0.50196078;stroke:#1798ff;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.50196078"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
id="path3046"
inkscape:connector-curvature="0" />
<path
style="fill:#0065b7;fill-opacity:0.63291141;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
id="path3048"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,440 @@
<?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="svg2568"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Lattice2_PopulateCopies_Plms_Move.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/Part/mystuff/Part_Compound_5_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2570">
<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="perspective2576" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3023">
<stop
id="stop3025"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3027"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3030">
<stop
id="stop3032"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3034"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3837"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3839"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3841"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3804"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3806"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3808"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3804-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<linearGradient
id="linearGradient3377-5">
<stop
id="stop3379-4"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381-8"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3806-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<linearGradient
id="linearGradient3080">
<stop
id="stop3082"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3084"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3808-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<linearGradient
id="linearGradient3087">
<stop
id="stop3089"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3091"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4368"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4370"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.9518802"
inkscape:cx="39.412699"
inkscape:cy="28.156141"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:object-nodes="true"
inkscape:snap-global="false"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata2573">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3794"
transform="matrix(0.66209119,0,0,0.66209119,16.272443,7.8325221)">
<path
inkscape:connector-curvature="0"
id="path3018"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
id="g3049"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.77833186,0,0,0.77833186,-2.3898253,0.89367113)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3045"
d="m 10.351377,24.493827 -5.6980057,0 0,25.925926 5.6980057,0"
style="fill:none;stroke:#000000;stroke-width:2.56959796;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<use
height="64"
width="64"
transform="matrix(-1,0,0,1,47.081698,0)"
id="use3047"
xlink:href="#path3045"
y="0"
x="0"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3823"
sodipodi:cx="53.466286"
sodipodi:cy="26.488129"
sodipodi:rx="7.5973411"
sodipodi:ry="7.5973411"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
transform="translate(-1.0080847,-16.969427)" />
<path
style="fill:none;stroke:#000000;stroke-width:1.49999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.602825,52.743051 18.817583,0 0,-35.787009"
id="path3866"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 30.091119,9.2273923 15.088091,0"
id="path3868"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 60.821116,9.5634205 7.392622,0"
id="path3868-3"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path3888"
sodipodi:cx="51.748352"
sodipodi:cy="14.099802"
sodipodi:rx="2.3521979"
sodipodi:ry="2.3521979"
d="m 54.10055,14.099802 a 2.3521979,2.3521979 0 1 1 -4.704396,0 2.3521979,2.3521979 0 1 1 4.704396,0 z"
transform="translate(0.84007066,-4.5363816)" />
<path
transform="translate(-1.0080848,3.5282969)"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
sodipodi:ry="7.5973411"
sodipodi:rx="7.5973411"
sodipodi:cy="26.488129"
sodipodi:cx="53.466286"
id="path4352"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 47.716014,29.893131 9.072763,0"
id="path4358"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.266798,29.725117 10.920919,0"
id="path4376"
inkscape:connector-curvature="0" />
<g
id="g3794-9"
transform="matrix(0.66209119,0,0,0.66209119,16.984575,-13.494373)">
<path
inkscape:connector-curvature="0"
id="path3018-4"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020-5"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022-5"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024-4"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
transform="matrix(0.66209119,0,0,0.66209119,16.312518,30.861358)"
id="use4372">
<path
style="fill:none;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
id="path3042"
inkscape:connector-curvature="0" />
<path
style="fill:#1798ff;fill-opacity:0.50210972;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
id="path3044"
inkscape:connector-curvature="0" />
<path
style="fill:#006eca;fill-opacity:0.50196078;stroke:#1798ff;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.50196078"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
id="path3046"
inkscape:connector-curvature="0" />
<path
style="fill:#0065b7;fill-opacity:0.63291141;stroke:#007ce0;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
id="path3048"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,441 @@
<?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="svg2568"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Lattice2_PopulateCopies_Move.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/Part/mystuff/Part_Compound_5_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2570">
<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="perspective2576" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3023">
<stop
id="stop3025"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3027"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3030">
<stop
id="stop3032"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3034"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3837"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3839"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3841"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3804"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3806"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3808"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3804-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<linearGradient
id="linearGradient3377-5">
<stop
id="stop3379-4"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3381-8"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3806-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<linearGradient
id="linearGradient3080">
<stop
id="stop3082"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3084"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient3808-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<linearGradient
id="linearGradient3087">
<stop
id="stop3089"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3091"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98773287,-0.06324662,0.02642229,1.230404,-216.68819,-80.013158)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4368"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69474204,0.27707782,-0.32964185,2.4645588,-139.05338,-247.09727)"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-5"
id="radialGradient4370"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.71303129,0,0,1.2312496,-173.62652,-89.498759)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.9518802"
inkscape:cx="8.9181336"
inkscape:cy="28.156141"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:object-nodes="true"
inkscape:snap-global="false"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata2573">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3794"
transform="matrix(0.66209119,0,0,0.66209119,16.272443,7.8325221)">
<path
inkscape:connector-curvature="0"
id="path3018"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
style="fill:none;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3020"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
style="fill:#e9a60a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3022"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
style="fill:#4c390a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3024"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
style="fill:#2f240a;fill-opacity:1;stroke:#000000;stroke-width:1.51036596px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
id="g3049"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.77833186,0,0,0.77833186,-2.3898253,0.89367113)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3045"
d="m 10.351377,24.493827 -5.6980057,0 0,25.925926 5.6980057,0"
style="fill:none;stroke:#000000;stroke-width:2.56959796;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<use
height="64"
width="64"
transform="matrix(-1,0,0,1,47.081698,0)"
id="use3047"
xlink:href="#path3045"
y="0"
x="0"
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3823"
sodipodi:cx="53.466286"
sodipodi:cy="26.488129"
sodipodi:rx="7.5973411"
sodipodi:ry="7.5973411"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
transform="translate(-1.0080847,-16.969427)" />
<g
id="g3798"
transform="matrix(0.94897349,0,0,0.94897349,-24.695619,-10.087879)">
<g
id="g3843"
transform="matrix(0.57659255,0,0,0.32499812,79.277735,9.6499853)">
<path
style="fill:url(#radialGradient4366);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -65.878042,4.7970936 -12.866966,10.1036774 21.744289,5.108296 0.30338,44.045609 11.486763,-13.03934 0.410614,-42.3363302 z"
id="path3845"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient4368);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -78.552461,15.155385 21.896364,4.143912 0,44.912523 -22.192265,-6.236008 0.295901,-42.820427 z"
id="path3847"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient4370);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.17218089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M -56.822875,19.354658 -44.896728,9.001326"
id="path3849"
inkscape:connector-curvature="0" />
</g>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1.49999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.602825,52.743051 18.817583,0 0,-35.787009"
id="path3866"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 30.091119,9.2273923 15.088091,0"
id="path3868"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 60.821116,9.5634205 7.392622,0"
id="path3868-3"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path3888"
sodipodi:cx="51.748352"
sodipodi:cy="14.099802"
sodipodi:rx="2.3521979"
sodipodi:ry="2.3521979"
d="m 54.10055,14.099802 a 2.3521979,2.3521979 0 1 1 -4.704396,0 2.3521979,2.3521979 0 1 1 4.704396,0 z"
transform="translate(0.84007066,-4.5363816)" />
<path
transform="translate(-1.0080848,3.5282969)"
d="m 61.063627,26.488129 a 7.5973411,7.5973411 0 1 1 -15.194682,0 7.5973411,7.5973411 0 1 1 15.194682,0 z"
sodipodi:ry="7.5973411"
sodipodi:rx="7.5973411"
sodipodi:cy="26.488129"
sodipodi:cx="53.466286"
id="path4352"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 47.716014,29.893131 9.072763,0"
id="path4358"
inkscape:connector-curvature="0" />
<g
transform="matrix(0.66209119,0,0,0.66209119,16.272443,31.186487)"
id="use4372">
<path
style="fill:none;stroke:#007ce0;stroke-width:1.51036595999999990px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -18.909091,25.818182 4.272727,17 30.454546,-11.545455 z"
id="path3042"
inkscape:connector-curvature="0" />
<path
style="fill:#1798ff;fill-opacity:0.50210971000000004;stroke:#007ce0;stroke-width:1.51036595999999990px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -14.636364,42.818182 15.818182,31.272727 -15.090909,28.545455 z"
id="path3044"
inkscape:connector-curvature="0" />
<path
style="fill:#006eca;fill-opacity:0.50196081;stroke:#1798ff;stroke-width:1.51036595999999990px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.50196081000000004"
d="m -18.909091,25.818182 4.272727,17 -0.454545,-14.272727 z"
id="path3046"
inkscape:connector-curvature="0" />
<path
style="fill:#0065b7;fill-opacity:0.63291138;stroke:#007ce0;stroke-width:1.51036595999999990px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -15.090909,28.545455 30.909091,2.727272 -34.727273,-5.454545 z"
id="path3048"
inkscape:connector-curvature="0" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 33.266798,29.725117 10.920919,0"
id="path4376"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -70,6 +70,20 @@ class LatticeArrayFilter(lattice2BaseFeature.LatticeFeature):
obj.Proxy = self obj.Proxy = self
def updateReadonlyness(self, selfobj, bypass_set = set()):
my_hidden = set([
'ReferencePlacement',
'ReferencePlacementLink',
'ReferencePlacementLinkIndex',
])
super(LatticeArrayFilter, self).updateReadonlyness(selfobj, bypass_set | my_hidden)
for prop in my_hidden:
if prop in bypass_set: continue
if hasattr(selfobj, prop):
selfobj.setEditorMode(prop, 2)
def recomputeReferencePlm(self, selfobj, selfplacements):
pass #suppress standard refplm recompute
def derivedExecute(self,obj): def derivedExecute(self,obj):
#validity check #validity check
@ -128,7 +142,9 @@ class LatticeArrayFilter(lattice2BaseFeature.LatticeFeature):
output.append(input[i]) output.append(input[i])
else: else:
raise ValueError('Filter mode not implemented:'+obj.FilterType) raise ValueError('Filter mode not implemented:'+obj.FilterType)
self.setReferencePlm(obj, lattice2BaseFeature.getReferencePlm(obj.Base))
return output return output
@ -192,7 +208,7 @@ def CreateLatticeArrayFilter(name,mode):
iLtc = 0 #index of lattice object in selection iLtc = 0 #index of lattice object in selection
iStc = 1 #index of stencil object in selection iStc = 1 #index of stencil object in selection
for i in range(0,len(sel)): for i in range(0,len(sel)):
if lattice2BaseFeature.isObjectLattice(sel[i]): if lattice2BaseFeature.isObjectLattice(sel[i].Object):
iLtc = i iLtc = i
iStc = i-1 #this may give negative index, but python accepts negative indexes iStc = i-1 #this may give negative index, but python accepts negative indexes
break break

View File

@ -40,7 +40,7 @@ EDIT_ATTACHMENT = 56 # Viewprovider edit mode number
def makeAttachablePlacement(name): def makeAttachablePlacement(name):
'''makeAttachablePlacement(name): makes an attachable Placement object.''' '''makeAttachablePlacement(name): makes an attachable Placement object.'''
if Compat.attach_extension_era: if Compat.attach_extension_era:
obj = lattice2BaseFeature.makeLatticeFeature(name, AttachablePlacement, ViewProviderAttachablePlacement, no_disable_attacher= True) obj = lattice2BaseFeature.makeLatticeFeature(name, AttachablePlacement, ViewProviderAttachablePlacement)
else: else:
#obsolete! #obsolete!
obj = FreeCAD.ActiveDocument.addObject("Part::AttachableObjectPython",name) obj = FreeCAD.ActiveDocument.addObject("Part::AttachableObjectPython",name)
@ -53,15 +53,12 @@ def makeAttachablePlacement(name):
class AttachableFeature(lattice2BaseFeature.LatticeFeature): class AttachableFeature(lattice2BaseFeature.LatticeFeature):
"Base class for attachable features" "Base class for attachable features"
attachable = True
def derivedInit(self,obj): def derivedInit(self,obj):
if Compat.attach_extension_era: if Compat.attach_extension_era:
if not obj.hasExtension('Part::AttachExtension'): #PartDesign-related hack: the placement already has attachextension if created in PD if not obj.hasExtension('Part::AttachExtension'): #PartDesign-related hack: the placement already has attachextension if created in PD
obj.addExtension('Part::AttachExtensionPython', None) obj.addExtension('Part::AttachExtensionPython', None)
def onDocumentRestored(self, selfobj):
#PartDesign-related hack: this dummy override disables disabling of attacher
pass
class AttachablePlacement(AttachableFeature): class AttachablePlacement(AttachableFeature):
"Attachable Lattice Placement object" "Attachable Lattice Placement object"
@ -122,9 +119,26 @@ class AttachedPlacementSubsequence(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyLink", "Base", "Lattice Attached Placement Subsequence", "Link to Lattice Attached Placement, which is to be subsequenced.") obj.addProperty("App::PropertyLink", "Base", "Lattice Attached Placement Subsequence", "Link to Lattice Attached Placement, which is to be subsequenced.")
obj.addProperty("App::PropertyString", "RefIndexFilter","Lattice Attached Placement Subsequence","Sets which references of attachment to cycle through children. '0000' = no cycle, '1000' = cycle only ref1. '' = cycle all if possible") obj.addProperty("App::PropertyString", "RefIndexFilter","Lattice Attached Placement Subsequence","Sets which references of attachment to cycle through children. '0000' = no cycle, '1000' = cycle only ref1. '' = cycle all if possible")
obj.addProperty("App::PropertyEnumeration", "CycleMode","Lattice Attached Placement Subsequence", "How to cycle through chidren. Open = advance each link till one reaches the end of array. Periodic = if array end reached, continue from begin if any children left.") obj.addProperty("App::PropertyEnumeration", "CycleMode","Lattice Attached Placement Subsequence", "How to cycle through children. Open = advance each link till one reaches the end of array. Periodic = if array end reached, continue from begin if any children left.")
obj.CycleMode = ['Open','Periodic'] obj.CycleMode = ['Open','Periodic']
def assureProperties(self, selfobj, creating_new = False):
super(AttachedPlacementSubsequence, self).assureProperties(selfobj, creating_new)
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'inherit', 'first placement', 'last placement'],
"Lattice Attached Placement Subsequence",
"Reference placement, corresponds to the original occurrence of the object to be populated. 'inherit' = use reference placement of the base attached placement."
)
if created:
selfobj.ReferencePlacementOption = 'inherit'
def recomputeReferencePlm(self, selfobj, selfplacements): #override
if selfobj.ReferencePlacementOption == 'external':
super(AttachedPlacementSubsequence, self).recomputeReferencePlm(selfobj, selfplacements)
#the remaining options are handled in derivedExecute
def derivedExecute(self,obj): def derivedExecute(self,obj):
attacher = Part.AttachEngine(screen(obj.Base).AttacherType) attacher = Part.AttachEngine(screen(obj.Base).AttacherType)
attacher.readParametersFromFeature(screen(obj.Base)) attacher.readParametersFromFeature(screen(obj.Base))
@ -133,10 +147,31 @@ class AttachedPlacementSubsequence(lattice2BaseFeature.LatticeFeature):
sublinks = Subsequencer.Subsequence_auto(attacher.References, sublinks = Subsequencer.Subsequence_auto(attacher.References,
loop= ('Till end' if obj.CycleMode == 'Open' else 'All around'), loop= ('Till end' if obj.CycleMode == 'Open' else 'All around'),
index_filter= ifilt) index_filter= ifilt)
deref = obj.Base.Placement.inverse()
basearray = [deref.multiply(plm) for plm in lattice2BaseFeature.getPlacementsList(obj.Base)]
plms = [] plms = []
for lnkval in sublinks: for lnkval in sublinks:
attacher.References = lnkval attacher.References = lnkval
plms.append(attacher.calculateAttachedPlacement(screen(obj.Base).Placement)) attplm = attacher.calculateAttachedPlacement(obj.Base.Placement)
plms.extend([attplm.multiply(plm) for plm in basearray])
#reference
ref = obj.ReferencePlacementOption
if ref == 'external':
pass #gets done in recomputeReferencePlm
elif ref == 'origin':
self.setReferencePlm(obj, None)
elif ref == 'inherit':
self.setReferencePlm(obj, lattice2BaseFeature.getReferencePlm(obj.Base))
elif ref == 'first placement':
self.setReferencePlm(obj, plms[0])
elif ref == 'last placement':
self.setReferencePlm(obj, plms[-1])
else:
raise NotImplementedError("Reference option not implemented: " + ref)
return plms return plms
class ViewProviderAttachedPlacementSubsequence(lattice2BaseFeature.ViewProviderLatticeFeature): class ViewProviderAttachedPlacementSubsequence(lattice2BaseFeature.ViewProviderLatticeFeature):

View File

@ -33,6 +33,7 @@ import lattice2CompoundExplorer as LCE
import lattice2Markers import lattice2Markers
import lattice2Executer import lattice2Executer
from lattice2ShapeCopy import shallowCopy from lattice2ShapeCopy import shallowCopy
import lattice2CoinGlue as CoinGlue
def getDefLatticeFaceColor(): def getDefLatticeFaceColor():
@ -49,11 +50,10 @@ def getDefShapeColor():
return (r/255.0, g/255.0, b/255.0, (255-o)/255.0) return (r/255.0, g/255.0, b/255.0, (255-o)/255.0)
def makeLatticeFeature(name, AppClass, ViewClass, no_body = False, no_disable_attacher = False): def makeLatticeFeature(name, AppClass, ViewClass, no_body = False):
'''makeLatticeFeature(name, AppClass, ViewClass, no_body = False): makes a document object for a LatticeFeature-derived object. '''makeLatticeFeature(name, AppClass, ViewClass, no_body = False): makes a document object for a LatticeFeature-derived object.
no_body: if False, the Lattice object will end up in an active body, and Part2DObject will be used. no_body: if False, the Lattice object will end up in an active body, and Part2DObject will be used.'''
no_disable_attacher: if True, attachment properties of Part2DObject won't be hidden'''
body = activeBody() body = activeBody()
if body and not no_body: if body and not no_body:
@ -73,15 +73,16 @@ def makeLatticeFeature(name, AppClass, ViewClass, no_body = False, no_disable_at
def isObjectLattice(documentObject): def isObjectLattice(documentObject):
'''isObjectLattice(documentObject): When operating on the object, it is to be treated as a lattice object. If False, treat as a regular shape.''' '''isObjectLattice(documentObject): When operating on the object, it is to be treated as a lattice object. If False, treat as a regular shape.'''
transform, src = source(documentObject)
ret = False ret = False
if hasattr(documentObject,"isLattice"): if hasattr(src,'isLattice'):
if 'On' in documentObject.isLattice: if 'On' in src.isLattice:
ret = True ret = True
if documentObject.isDerivedFrom('PartDesign::ShapeBinder'): #if documentObject.isDerivedFrom('PartDesign::ShapeBinder'):
if len(documentObject.Support) == 1 and documentObject.Support[0][1] == ('',): # if len(documentObject.Support) == 1 and documentObject.Support[0][1] == ('',):
ret = isObjectLattice(documentObject.Support[0][0]) # ret = isObjectLattice(documentObject.Support[0][0])
if hasattr(documentObject, 'IAm') and documentObject.IAm == 'PartOMagic.Ghost': #if hasattr(documentObject, 'IAm') and documentObject.IAm == 'PartOMagic.Ghost':
ret = isObjectLattice(documentObject.Base) # ret = isObjectLattice(documentObject.Base)
return ret return ret
def getMarkerSizeEstimate(ListOfPlacements): def getMarkerSizeEstimate(ListOfPlacements):
@ -103,13 +104,15 @@ def getMarkerSizeEstimate(ListOfPlacements):
class LatticeFeature(object): class LatticeFeature(object):
"Base object for lattice objects (arrays of placements)" "Base object for lattice objects (arrays of placements)"
attachable = False
def __init__(self,obj): def __init__(self,obj):
# please, don't override. Override derivedInit instead. # please, don't override. Override derivedInit instead.
obj.addProperty('App::PropertyString', 'Type', "Lattice", "module_name.class_name of this object, for proxy recovery", 0, True, True) obj.addProperty('App::PropertyString', 'Type', "Lattice", "module_name.class_name of this object, for proxy recovery", 0, True, True)
obj.Type = self.__module__ + '.' + type(self).__name__ obj.Type = self.__module__ + '.' + type(self).__name__
prop = "NumElements" prop = "NumElements"
obj.addProperty("App::PropertyInteger",prop,"Lattice","Info: number of placements in the array") obj.addProperty("App::PropertyInteger",prop,"Lattice","Info: number of placements in the array", 0, True)
obj.setEditorMode(prop, 1) # set read-only obj.setEditorMode(prop, 1) # set read-only
obj.addProperty("App::PropertyLength","MarkerSize","Lattice","Size of placement markers (set to zero for automatic).") obj.addProperty("App::PropertyLength","MarkerSize","Lattice","Size of placement markers (set to zero for automatic).")
@ -123,25 +126,115 @@ class LatticeFeature(object):
# Auto-On an Auto-Off can be modified when recomputing. Force values are going to stay. # Auto-On an Auto-Off can be modified when recomputing. Force values are going to stay.
prop = "ExposePlacement" prop = "ExposePlacement"
obj.addProperty("App::PropertyBool",prop,"Lattice","Makes the placement syncronized to Placement property. This will oftem make this object unmoveable. Not applicable to arrays.") obj.addProperty("App::PropertyBool",prop,"Lattice","Makes the placement syncronized to Placement property. This will often make this object unmoveable. Not applicable to arrays.")
self.derivedInit(obj) self.derivedInit(obj)
self.assureProperties(obj, creating_new= True)
self.updateReadonlyness(obj)
if not self.attachable:
self.disableAttacher(obj)
obj.Proxy = self obj.Proxy = self
def assureProperties(self, selfobj, creating_new = False):
"""#overrideme Method to reconstruct missing properties, that appeared as new functionality was introduced.
Auto called from __init__ (and before derivedInit), and from execute (before derivedExecute)."""
self.assureProperty(selfobj, 'App::PropertyLink', 'ReferencePlacementLink', None, "Lattice", "Link to placement to use as reference placement")
self.assureProperty(selfobj, 'App::PropertyString', 'ReferencePlacementLinkIndex', None, "Lattice", "Index of placement to take from the link. Can also be 'self.0' for own placements.")
self.assureProperty(selfobj, 'App::PropertyBool', 'ReferencePlacementInGlobal', True, "Lattice", "True if reference placement property is in global cs. ", readonly= True)
self.assureProperty(
selfobj,
'App::PropertyPlacement',
'ReferencePlacement',
None,
"Lattice",
"Reference placement, used by 'Populate: build array'. For it, all placements in this array are reinterpreted as relative to this one.",
readonly= True
)
def updateReadonlyness(self, selfobj, bypass_set = set()):
is_lattice = isObjectLattice(selfobj)
extref = 0
if hasattr(selfobj, 'ReferencePlacementOption'):
extref = 0 if selfobj.ReferencePlacementOption == 'external' else 1
rodict = {
'NumElements': 1,
'MarkerSize': 0,
'MarkerShape': 0,
'ReferencePlacement': 1,
'ReferencePlacementLink': extref,
'ReferencePlacementLinkIndex': extref,
'ReferencePlacementInGlobal': 1,
}
for prop in rodict:
if prop in bypass_set: continue
if hasattr(selfobj, prop):
selfobj.setEditorMode(prop, rodict[prop] if is_lattice else 2)
def assureProperty(self, selfobj, proptype, propname, defvalue, group, tooltip): def assureProperty(self, selfobj, proptype, propname, defvalue, group, tooltip, readonly = False, hidden = False):
"""assureProperty(selfobj, proptype, propname, defvalue, group, tooltip): adds """assureProperty(selfobj, proptype, propname, defvalue, group, tooltip): adds
a property if one is missing, and sets its value to default. Does nothing if property a property if one is missing, and sets its value to default. Does nothing if property
already exists. Returns True if property was created, or False if not.""" already exists. Returns True if property was created, or False if not."""
return assureProperty(selfobj, proptype, propname, defvalue, group, tooltip) return assureProperty(selfobj, proptype, propname, defvalue, group, tooltip, readonly, hidden)
def setReferencePlm(self, selfobj, refplm, in_global = False):
"""setReferencePlm(selfobj, refplm, in_global = False): sets reference placement, in internal CS."""
attr = 'ReferencePlacement'
if refplm is None:
refplm = App.Placement()
in_global = True
if selfobj.ExposePlacement:
in_global = True
selfobj.ReferencePlacementInGlobal = in_global
selfobj.ReferencePlacement = refplm
def getReferencePlm(self, selfobj, in_global = False):
"""getReferencePlm(self, selfobj): Returns reference placement in internal CS, or in global CS."""
if not isObjectLattice(selfobj):
return None
if not hasattr(selfobj, 'ReferencePlacement'):
return App.Placement() if in_global else selfobj.Placement.inverse()
if in_global == selfobj.ReferencePlacementInGlobal:
return selfobj.ReferencePlacement
elif in_global == True and selfobj.ReferencePlacementInGlobal == False:
#goal: return == selfobj.Placement * refplm
return selfobj.Placement.multiply(selfobj.ReferencePlacement)
elif in_global == False and selfobj.ReferencePlacementInGlobal == True:
#goal: self.Placement * return == refplm
return selfobj.Placement.inverse().multiply(selfobj.ReferencePlacement)
def recomputeReferencePlm(self, selfobj, selfplacements):
lnk = selfobj.ReferencePlacementLink
strindex = selfobj.ReferencePlacementLinkIndex
is_selfref = lnk is None and strindex.startswith('self.')
ref = selfobj if is_selfref else lnk
if ref is None:
self.setReferencePlm(selfobj, None)
else:
if is_selfref:
index = int(strindex[len('self.'):])
elif len(strindex)>0:
index = int(strindex)
else:
index = 0
if is_selfref:
refplm = selfplacements[index]
self.setReferencePlm(selfobj, refplm, in_global= False)
else:
refplm = getPlacementsList(ref)[index]
self.setReferencePlm(selfobj, refplm, in_global= True)
def derivedInit(self, obj): def derivedInit(self, obj):
'''for overriding by derived classes''' '''for overriding by derived classes'''
pass pass
def execute(self,obj): def execute(self,obj):
# please, don't override. Override derivedExecute instead. # please, don't override. Override derivedExecute instead.
self.assureProperties(obj)
plms = self.derivedExecute(obj) plms = self.derivedExecute(obj)
@ -154,6 +247,8 @@ class LatticeFeature(object):
if markerSize < DistConfusion: if markerSize < DistConfusion:
markerSize = getMarkerSizeEstimate(plms) markerSize = getMarkerSizeEstimate(plms)
marker = lattice2Markers.getPlacementMarker(scale= markerSize, markerID= obj.MarkerShape) marker = lattice2Markers.getPlacementMarker(scale= markerSize, markerID= obj.MarkerShape)
self.assureProperty(obj, 'App::PropertyLength', 'MarkerSizeActual', markerSize, "Lattice", "Size of placement markers of this array", hidden= True)
obj.MarkerSizeActual = markerSize
bExposing = False bExposing = False
if obj.ExposePlacement: if obj.ExposePlacement:
@ -183,6 +278,7 @@ class LatticeFeature(object):
if obj.isLattice == 'Auto-Off': if obj.isLattice == 'Auto-Off':
obj.isLattice = 'Auto-On' obj.isLattice = 'Auto-On'
self.recomputeReferencePlm(obj, plms)
else: else:
# DerivedExecute didn't return anything. Thus we assume it # DerivedExecute didn't return anything. Thus we assume it
# has assigned the shape, and thus we don't do anything. # has assigned the shape, and thus we don't do anything.
@ -190,6 +286,7 @@ class LatticeFeature(object):
if obj.isLattice == 'Auto-On': if obj.isLattice == 'Auto-On':
obj.isLattice = 'Auto-Off' obj.isLattice = 'Auto-Off'
# i don't remember, wtf is going on here...
if obj.ExposePlacement: if obj.ExposePlacement:
if obj.Shape.ShapeType == "Compound": if obj.Shape.ShapeType == "Compound":
children = obj.Shape.childShapes() children = obj.Shape.childShapes()
@ -201,7 +298,7 @@ class LatticeFeature(object):
else: else:
#nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized. #nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized.
pass pass
return self.updateReadonlyness(obj)
def derivedExecute(self,obj): def derivedExecute(self,obj):
'''For overriding by derived class. If this returns a list of placements, '''For overriding by derived class. If this returns a list of placements,
@ -262,13 +359,36 @@ class LatticeFeature(object):
selfobj.MapMode = selfobj.MapMode #trigger attachment, to make it update property states selfobj.MapMode = selfobj.MapMode #trigger attachment, to make it update property states
def onDocumentRestored(self, selfobj): def onDocumentRestored(self, selfobj):
#override to have attachment! if not self.attachable:
self.disableAttacher(selfobj) self.disableAttacher(selfobj)
self.assureProperties(selfobj)
self.updateReadonlyness(selfobj)
class ViewProviderLatticeFeature(object): class ViewProviderLatticeFeature(object):
"A View Provider for base lattice object" "A View Provider for base lattice object"
Object = None # documentobject the vp is attached to
ViewObject = None # viewprovider this proxy is attached to
#coin graph:
# transform #in sync with Placement
# coordinate3 #coordinates for main shape rendering
# switch: #main display mode switch, == self.modenode
# ...
# separator: #reference placement related stuff, == self.refplm_node
# transform #reference placement, == self.refplm_tr
# separator: #actual shape of reference placement, == self.refplm_sh
# ...
# switch: #mode switch of reference placement, == self.modenode_refplm
# ...
modenode = None # main displaymode switch node
refplm_node = None # the node containing everything related to reference placement
refplm_tr = None #transform node of reference placement
refplm_sh = None #node containing the shape of reference placement
modenode_refplm = None # displaymode switch node for reference placement
def __init__(self,vobj): def __init__(self,vobj):
'''Don't override. Override derivedInit, please!''' '''Don't override. Override derivedInit, please!'''
vobj.Proxy = self vobj.Proxy = self
@ -291,13 +411,44 @@ class ViewProviderLatticeFeature(object):
FreeCAD.Console.PrintError("__init__() of lattice object view provider is overridden. Please don't! Fix it!\n") FreeCAD.Console.PrintError("__init__() of lattice object view provider is overridden. Please don't! Fix it!\n")
except AttributeError as err: except AttributeError as err:
pass # quick-n-dirty fix for Py3. TODO: restore the functionality in Py3, or remove this routine altogether. pass # quick-n-dirty fix for Py3. TODO: restore the functionality in Py3, or remove this routine altogether.
def fixProxy(self, vobj):
if vobj is not self.ViewObject:
vobj.Proxy = vobj.ProxyBackup
raise RuntimeError('fixing broken proxy...')
def getIcon(self): def getIcon(self):
return getIconPath("Lattice.svg") return getIconPath("Lattice.svg")
def attach(self, vobj): def attach(self, vobj):
self.ViewObject = vobj self.ViewObject = vobj
self.Object = vobj.Object self.Object = vobj.Object
try:
vobj.ProxyBackup = self
except Exception:
vobj.addProperty('App::PropertyPythonObject', 'ProxyBackup', 'Base', "helper property for workaround FC bug #3564", 0, False, True)
vobj.ProxyBackup = self
self.makeRefplmVisual(vobj)
from pivy import coin
self.modenode = next((node for node in vobj.RootNode.getChildren() if node.isOfType(coin.SoSwitch.getClassTypeId())))
def makeRefplmVisual(self, vobj):
import pivy
from pivy import coin
refplm = self.Object.Proxy.getReferencePlm(self.Object)
if refplm is not None:
if not hasattr(self.Object, 'MarkerSizeActual'): return
if self.refplm_node is None:
self.refplm_node, self.refplm_tr, self.refplm_sh = lattice2Markers.getRefPlmMarker(self.Object.MarkerShape)
vobj.RootNode.addChild(self.refplm_node)
self.modenode_refplm = next((node for node in self.refplm_sh.getChildren() if node.isOfType(coin.SoSwitch.getClassTypeId())))
CoinGlue.cointransform(refplm, float(self.Object.MarkerSizeActual) * 1.1, self.refplm_tr)
else:
if hasattr(self, 'refplm_node') and self.refplm_node is not None:
vobj.RootNode.removeChild(self.refplm_node)
self.refplm_node, self.refplm_tr, self.refplm_sh = None, None, None
self.modenode_refplm = None
def __getstate__(self): def __getstate__(self):
return None return None
@ -324,10 +475,21 @@ class ViewProviderLatticeFeature(object):
# catch all exceptions, because we don't want to prevent deletion if something goes wrong # catch all exceptions, because we don't want to prevent deletion if something goes wrong
FreeCAD.Console.PrintError("Error in onDelete: " + str(err)) FreeCAD.Console.PrintError("Error in onDelete: " + str(err))
return True return True
def updateData(self, obj, prop):
if prop in ['ReferencePlacement', 'MarkerSizeActual', 'Placement', 'ReferencePlacementInGlobal', 'isLattice']:
self.fixProxy(obj.ViewObject)
self.makeRefplmVisual(obj.ViewObject)
def onChanged(self, vobj, prop):
if prop == 'Visibility':
if self.modenode_refplm is not None:
self.modenode_refplm.whichChild.setValue(0 if vobj.Visibility == True else -1)
def assureProperty(docobj, proptype, propname, defvalue, group, tooltip): def assureProperty(docobj, proptype, propname, defvalue, group, tooltip, readonly = False, hidden = False):
"""assureProperty(docobj, proptype, propname, defvalue, group, tooltip): adds """assureProperty(docobj, proptype, propname, defvalue, group, tooltip, readonly = False, hidden = False): adds
a property if one is missing, and sets its value to default. Does nothing if property a property if one is missing, and sets its value to default. Does nothing if property
already exists. Returns True if property was created, or False if not.""" already exists. Returns True if property was created, or False if not."""
@ -335,7 +497,7 @@ def assureProperty(docobj, proptype, propname, defvalue, group, tooltip):
#todo: check type match #todo: check type match
return False return False
docobj.addProperty(proptype, propname, group, tooltip) docobj.addProperty(proptype, propname, group, tooltip, 0, readonly, hidden)
if defvalue is not None: if defvalue is not None:
setattr(docobj, propname, defvalue) setattr(docobj, propname, defvalue)
return True return True
@ -348,7 +510,7 @@ def makeMoveFromTo(plmFrom, plmTo):
from one placement to another placement''' from one placement to another placement'''
return plmTo.multiply(plmFrom.inverse()) return plmTo.multiply(plmFrom.inverse())
def getPlacementsList(documentObject, context = None, suppressWarning = False): def getPlacementsList(documentObject, context = None, suppressWarning = False, dereferenced = False, torefplm = App.Placement()):
'''getPlacementsList(documentObject, context = None): extract list of placements '''getPlacementsList(documentObject, context = None): extract list of placements
from an array object. Context is an object to report as context, when displaying from an array object. Context is an object to report as context, when displaying
a warning if the documentObject happens to be a non-lattice.''' a warning if the documentObject happens to be a non-lattice.'''
@ -356,7 +518,46 @@ def getPlacementsList(documentObject, context = None, suppressWarning = False):
if not suppressWarning: if not suppressWarning:
lattice2Executer.warning(context, documentObject.Name + " is not a placement or an array of placements. Results may be unexpected.") lattice2Executer.warning(context, documentObject.Name + " is not a placement or an array of placements. Results may be unexpected.")
leaves = LCE.AllLeaves(documentObject.Shape) leaves = LCE.AllLeaves(documentObject.Shape)
return [leaf.Placement for leaf in leaves] if not dereferenced:
return [leaf.Placement for leaf in leaves]
else:
# goal: refplm * derefplm == it
# return = torefplm * derefplm
# => return = torefplm * refplm.inverse * it
operator = torefplm.multiply(getReferencePlm(documentObject).inverse())
return [operator.multiply(leaf.Placement) for leaf in leaves]
def getReferencePlm(feature):
"""Obtains reference placement, in container's CS (includes feature.Placement)."""
transform, src = source(feature)
if not isObjectLattice(src):
raise TypeError('getReferencePlm: array of placements expected, got something else.')
return transform.multiply(src.Proxy.getReferencePlm(src))
def source(feature):
"""source(feature): finds the original Lattice array feature from behind shapebinders and such. Returns (transform, lattice_feature).
transform: placement that converts feature's local coordinates into global.
lattice_feature may not actually be an array of placements."""
def _source(feature, visitset):
if hasattr(feature,'isLattice'):
return (feature.Placement, feature)
if feature in visitset:
raise RuntimeError("Dependency loop!")
visitset.append(feature)
if feature.isDerivedFrom('PartDesign::ShapeBinder'):
if len(feature.Support) == 1 and feature.Support[0][1] == ('',):
base = feature.Support[0][0]
transform1, src = _source(base, visitset)
transform = feature.Placement.multiply(base.Placement.inverse().multiply(transform1))
return (transform, src)
if hasattr(feature, 'IAm') and feature.IAm == 'PartOMagic.Ghost':
base = feature.Base
transform1, src = _source(base, visitset)
transform = feature.Placement.multiply(base.Placement.inverse().multiply(transform1))
return (transform, src)
return (feature.Placement, feature)
return _source(feature, list())
def splitSelection(sel): def splitSelection(sel):
'''splitSelection(sel): splits sel (use getSelectionEx()) into lattices and non-lattices. '''splitSelection(sel): splits sel (use getSelectionEx()) into lattices and non-lattices.

49
lattice2CoinGlue.py Normal file
View File

@ -0,0 +1,49 @@
#***************************************************************************
#* *
#* Copyright (c) 2018 - Victor Titov (DeepSOIC) *
#* <vv.titov@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
__title__="CoinGlue module of FreeCAD add-on Lattice2"
__author__ = "DeepSOIC"
__url__ = ""
__doc__ = "Glue and conversion routines between coin and freecad"
def cointransform(placement, scale = 1.0, modifyme = None):
"""cointransform(placement, scale = 1.0, modifyme = None): creates/updates SoTransform node from FreeCAD.Placement.
modifyme: the existing node to be modified.
Returns: SoTransform node (new if modifyme is None else modifyme)"""
from pivy import coin
tr = coin.SoTransform() if modifyme is None else modifyme
tr.scaleFactor.setValue(scale,scale,scale)
tr.translation.setValue(*tuple(placement.Base))
tr.rotation.setValue(*placement.Rotation.Q)
return tr
def readNodeFromFile(fullpath):
"""readNodeFromFile(fullpath): reads a file. Returns SoSeparator node, containing the read out stuff."""
from pivy import coin
i = coin.SoInput()
if not i.openFile(fullpath): raise ValueError("Failed to open file: {fn}".format(fn= fullpath))
import pivy
sep = pivy.SoDB.readAll(i)
i.closeFile()
return sep

View File

@ -25,16 +25,11 @@ __title__="Lattice Invert object: creates an array of placements from a compound
__author__ = "DeepSOIC" __author__ = "DeepSOIC"
__url__ = "" __url__ = ""
import math
import FreeCAD as App import FreeCAD as App
import Part import Part
from lattice2Common import * from lattice2Common import *
import lattice2BaseFeature import lattice2BaseFeature
import lattice2CompoundExplorer as LCE
import lattice2GeomUtils as Utils
import lattice2Executer
# -------------------------- document object -------------------------------------------------- # -------------------------- document object --------------------------------------------------
@ -46,8 +41,6 @@ class LatticeInvert(lattice2BaseFeature.LatticeFeature):
"The Lattice Invert object" "The Lattice Invert object"
def derivedInit(self,obj): def derivedInit(self,obj):
self.Type = "LatticeInvert"
obj.addProperty("App::PropertyLink","Base","Lattice Invert","Lattice, all the placements of which are to be inverted.") obj.addProperty("App::PropertyLink","Base","Lattice Invert","Lattice, all the placements of which are to be inverted.")
obj.addProperty("App::PropertyEnumeration","TranslateMode","Lattice Invert","What to do with translation part of placements") obj.addProperty("App::PropertyEnumeration","TranslateMode","Lattice Invert","What to do with translation part of placements")
@ -57,14 +50,27 @@ class LatticeInvert(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyEnumeration","OrientMode","Lattice Invert","what to do with orientation part of placements") obj.addProperty("App::PropertyEnumeration","OrientMode","Lattice Invert","what to do with orientation part of placements")
obj.OrientMode = ['invert', 'keep', 'reset'] obj.OrientMode = ['invert', 'keep', 'reset']
obj.OrientMode = 'invert' obj.OrientMode = 'invert'
def assureProperties(self, selfobj, creating_new = False):
super(LatticeInvert, self).assureProperties(selfobj, creating_new)
self.assureProperty(selfobj, 'App::PropertyEnumeration', 'Referencing', ['Origin', 'Array\'s reference'], "Lattice Invert", "Sets which placement to use as origin")
def derivedExecute(self,obj): def derivedExecute(self,obj):
# cache stuff # cache stuff
base = screen(obj.Base).Shape placements = lattice2BaseFeature.getPlacementsList(obj.Base)
if not lattice2BaseFeature.isObjectLattice(screen(obj.Base)):
lattice2Executer.warning(obj, "Base is not a lattice, but lattice is expected. Results may be unexpected.\n") # dereference
baseChildren = LCE.AllLeaves(base) refplm = App.Placement()
if obj.Referencing == 'Origin':
pass
elif obj.Referencing == 'Array\'s reference':
refplm = self.getReferencePlm(obj.Base)
self.setReferencePlm(obj, refplm)
else:
raise NotImplementedError(obj.Referencing)
inv_refplm = refplm.inverse()
locplms = [inv_refplm.multiply(plm) for plm in placements]
#cache mode comparisons, for speed #cache mode comparisons, for speed
posIsInvert = obj.TranslateMode == 'invert' posIsInvert = obj.TranslateMode == 'invert'
posIsKeep = obj.TranslateMode == 'keep' posIsKeep = obj.TranslateMode == 'keep'
@ -78,26 +84,29 @@ class LatticeInvert(lattice2BaseFeature.LatticeFeature):
outputPlms = [] #list of placements outputPlms = [] #list of placements
# the essence # the essence
for child in baseChildren: for plm in locplms:
pos = App.Vector() pos = App.Vector()
ori = App.Rotation() ori = App.Rotation()
inverted = child.Placement.inverse() inverted = plm.inverse()
if posIsInvert: if posIsInvert:
pos = inverted.Base pos = inverted.Base
elif posIsKeep: elif posIsKeep:
pos = child.Placement.Base pos = plm.Base
elif posIsReset: elif posIsReset:
pass pass
if oriIsInvert: if oriIsInvert:
ori = inverted.Rotation ori = inverted.Rotation
elif oriIsKeep: elif oriIsKeep:
ori = child.Placement.Rotation ori = plm.Rotation
elif oriIsReset: elif oriIsReset:
pass pass
plm = App.Placement(pos, ori) outputPlms.append(App.Placement(pos, ori))
outputPlms.append(plm)
# re-reference
outputPlms = [refplm.multiply(plm) for plm in outputPlms]
return outputPlms return outputPlms
@ -121,6 +130,8 @@ def CreateLatticeInvert(name):
FreeCADGui.addModule("lattice2Executer") FreeCADGui.addModule("lattice2Executer")
FreeCADGui.doCommand("f = lattice2Invert.makeLatticeInvert(name='"+name+"')") FreeCADGui.doCommand("f = lattice2Invert.makeLatticeInvert(name='"+name+"')")
FreeCADGui.doCommand("f.Base = App.ActiveDocument."+sel[0].ObjectName) FreeCADGui.doCommand("f.Base = App.ActiveDocument."+sel[0].ObjectName)
hasref = lattice2BaseFeature.getReferencePlm(sel[0].Object) is not None
FreeCADGui.doCommand("f.Referencing = {r}".format(r= repr('Array\'s reference' if hasref else 'Origin') ))
FreeCADGui.doCommand("for child in f.ViewObject.Proxy.claimChildren():\n"+ FreeCADGui.doCommand("for child in f.ViewObject.Proxy.claimChildren():\n"+
" child.ViewObject.hide()") " child.ViewObject.hide()")
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)") FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")

View File

@ -49,33 +49,60 @@ class JoinArrays(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyBool","Interleave","Lattice JoinArrays","If false, first go all elements of array 1, nect go all elements of array 2, so on. If true, first go all first elements from each array, then all second elements, and so on.") obj.addProperty("App::PropertyBool","Interleave","Lattice JoinArrays","If false, first go all elements of array 1, nect go all elements of array 2, so on. If true, first go all first elements from each array, then all second elements, and so on.")
def assureProperties(self, selfobj, creating_new = False):
super(JoinArrays, self).assureProperties(selfobj, creating_new = False)
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'inherit 1st'],
"Lattice JoinArrays",
"Reference placement, corresponds to the original occurrence of the object to be populated."
)
if created:
selfobj.ReferencePlacementOption = 'inherit 1st'
self.assureProperty(selfobj,
'App::PropertyBool',
'AlignReferences',
False,
"Lattice JoinArrays",
"If true, input arrays will be moved to make their reference placements equal, before joining."
)
def recomputeReferencePlm(self, selfobj, selfplacements): #override
pass #disables standard recompute-reference call. The recompute is handled by derivedExecute
def derivedExecute(self,obj): def derivedExecute(self, selfobj):
#validity check align = selfobj.AlignReferences
nonLattices = [] #recompute reference placement
for iArr in range(0, len(obj.Links)): ref = selfobj.ReferencePlacementOption
link = obj.Links[iArr] if ref == 'external':
if not lattice2BaseFeature.isObjectLattice(link): super(JoinArrays, self).recomputeReferencePlm(selfobj, [])
nonLattices.append(link.Label) elif ref == 'origin':
if len(nonLattices) > 0: self.setReferencePlm(selfobj, None)
lattice2Executer.warning(obj, "Only lattice objects are expected to be linked as arrays in JoinArrays. There are " elif ref == 'inherit 1st':
+len(nonLattices)+" objects which are not lattice objects. Results may me unexpected.") if len(selfobj.Links)>0:
self.setReferencePlm(selfobj, lattice2BaseFeature.getReferencePlm(selfobj.Links[0]))
else:
self.setReferencePlm(selfobj, None)
else:
raise NotImplementedError("Reference option not implemented: " + ref)
refplm = self.getReferencePlm(selfobj)
#extract placements #extract placements
listlistPlms = [] listlistPlms = []
lengths = [] lengths = []
for link in obj.Links: for link in selfobj.Links:
leaves = LCE.AllLeaves(link.Shape) plms = lattice2BaseFeature.getPlacementsList(link, context= selfobj, dereferenced= align, torefplm = refplm)
listlistPlms.append([child.Placement for child in leaves]) listlistPlms.append(plms)
lengths.append(len(leaves)) lengths.append(len(plms))
#processing #processing
output = [] #list of placements output = [] #list of placements
if obj.Interleave: if selfobj.Interleave:
for l in lengths[1:]: for l in lengths[1:]:
if l != lengths[0]: if l != lengths[0]:
lattice2Executer.warning(obj,"Array lengths are unequal: "+repr(lengths)+". Interleaving will be inconsistent.") lattice2Executer.warning(selfobj,"Array lengths are unequal: "+repr(lengths)+". Interleaving will be inconsistent.")
break break
for iItem in range(0,max(lengths)): for iItem in range(0,max(lengths)):
@ -85,6 +112,7 @@ class JoinArrays(lattice2BaseFeature.LatticeFeature):
else: else:
for list in listlistPlms: for list in listlistPlms:
output.extend(list) output.extend(list)
return output return output
class ViewProviderJoinArrays(lattice2BaseFeature.ViewProviderLatticeFeature): class ViewProviderJoinArrays(lattice2BaseFeature.ViewProviderLatticeFeature):
@ -125,14 +153,13 @@ class _CommandJoinArrays:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_JoinArrays","Lattice JoinArrays: concatenate or interleave two or more arrays.")} 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_JoinArrays","Lattice JoinArrays: concatenate or interleave two or more arrays.")}
def Activated(self): def Activated(self):
if len(FreeCADGui.Selection.getSelection()) > 1 : try:
CreateJoinArrays(name = "Join") if len(FreeCADGui.Selection.getSelection()) > 1 :
else: CreateJoinArrays(name = "Join")
mb = QtGui.QMessageBox() else:
mb.setIcon(mb.Icon.Warning) infoMessage("Please select at least two lattice objects. Selected lattice objects will be concatenated or interleaved into one array.")
mb.setText(translate("Lattice2_JoinArrays", "Please select at least two lattice objects. Selected lattice objects will be concatenated or interleaved into one array.", None)) except Exception as err:
mb.setWindowTitle(translate("Lattice2_JoinArrays","Bad selection", None)) msgError(err)
mb.exec_()
def IsActive(self): def IsActive(self):
if FreeCAD.ActiveDocument: if FreeCAD.ActiveDocument:

View File

@ -80,16 +80,17 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
obj.Step = 3.0 obj.Step = 3.0
obj.Count = 5.0 obj.Count = 5.0
self.assureProperties(obj)
def updateReadonlyness(self, obj): def updateReadonlyness(self, obj):
super(LinearArray,self).updateReadonlyness(obj)
link = screen(obj.Link) link = screen(obj.Link)
obj.setEditorMode("Dir", 1 if (link and obj.DirIsDriven) else 0) obj.setEditorMode("Dir", 1 if (link and obj.DirIsDriven) else 0)
obj.setEditorMode("Point", 1 if (link and obj.PointIsDriven) else 0) obj.setEditorMode("Point", 1 if (link and obj.PointIsDriven) else 0)
obj.setEditorMode("DirIsDriven", 0 if link else 1) obj.setEditorMode("DirIsDriven", 0 if link else 1)
obj.setEditorMode("PointIsDriven", 0 if link else 1) obj.setEditorMode("PointIsDriven", 0 if link else 1)
obj.setEditorMode("DrivenProperty", 0 if link else 1) obj.setEditorMode("DrivenProperty", 0 if link else 1)
obj.setEditorMode('ReferenceValue', 0 if obj.ReferencePlacementOption == 'at custom value' else 2)
self.assureGenerator(obj)
self.generator.updateReadonlyness() self.generator.updateReadonlyness()
def assureGenerator(self, obj): def assureGenerator(self, obj):
@ -101,15 +102,30 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
groupname_gen= "Lattice Series Generator", groupname_gen= "Lattice Series Generator",
valuesdoc= "List of distances. Distance is measured from Point, along Dir, in millimeters.", valuesdoc= "List of distances. Distance is measured from Point, along Dir, in millimeters.",
valuestype= "App::PropertyDistance") valuestype= "App::PropertyDistance")
self.updateReadonlyness(obj)
def assureProperties(self, selfobj): def assureProperties(self, selfobj, creating_new = False):
super(LinearArray, self).assureProperties(selfobj, creating_new)
assureProperty(selfobj, "App::PropertyLinkSub", "SubLink", sublinkFromApart(screen(selfobj.Link), selfobj.LinkSubelement), "Lattice Array", "Mirror of Object+SubNames properties") assureProperty(selfobj, "App::PropertyLinkSub", "SubLink", sublinkFromApart(screen(selfobj.Link), selfobj.LinkSubelement), "Lattice Array", "Mirror of Object+SubNames properties")
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'SpanStart', 'SpanEnd', 'at custom value', 'first placement', 'last placement'],
"Lattice Array",
"Reference placement, corresponds to the original occurrence of the object to be populated."
)
if created:
selfobj.ReferencePlacementOption = 'SpanStart'
self.assureProperty(selfobj, 'App::PropertyDistance', 'ReferenceValue', 0.0, "Lattice Array", "Sets the value to use for generating ReferencePlacement. This value sets, what coordinate the object to be populated corresponds to.")
def recomputeReferencePlm(self, selfobj, selfplacements): #override
if selfobj.ReferencePlacementOption == 'external':
super(LinearArray, self).recomputeReferencePlm(selfobj, selfplacements)
#the remaining options are handled in derivedExecute
def derivedExecute(self,obj): def derivedExecute(self,obj):
self.assureGenerator(obj) self.assureGenerator(obj)
self.assureProperties(obj)
self.updateReadonlyness(obj)
# Apply links # Apply links
if screen(obj.Link): if screen(obj.Link):
@ -170,9 +186,30 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
dir.normalize() dir.normalize()
# Make the array # Make the array
def plmByVal(val):
return App.Placement(obj.Point + obj.Dir*val, ori)
output = [] # list of placements output = [] # list of placements
for v in values: for v in values:
output.append( App.Placement(obj.Point + obj.Dir*v, ori) ) output.append( plmByVal(v) )
# update reference placement
ref = obj.ReferencePlacementOption
if ref == 'external':
pass
elif ref == 'origin':
self.setReferencePlm(obj, None)
elif ref == 'SpanStart':
self.setReferencePlm(obj, plmByVal(float(obj.SpanStart)))
elif ref == 'SpanEnd':
self.setReferencePlm(obj, plmByVal(float(obj.SpanEnd)))
elif ref == 'at custom value':
self.setReferencePlm(obj, plmByVal(float(obj.ReferenceValue)))
elif ref == 'first placement':
self.setReferencePlm(obj, output[0])
elif ref == 'last placement':
self.setReferencePlm(obj, output[-1])
else:
raise NotImplementedError("Reference option not implemented: " + ref)
return output return output

View File

@ -21,15 +21,19 @@
#* * #* *
#*************************************************************************** #***************************************************************************
import Part, os import Part
import os
import lattice2CoinGlue as CoinGlue
__title__="latticeMarkers module for FreeCAD" __title__="latticeMarkers module for FreeCAD"
__author__ = "DeepSOIC" __author__ = "DeepSOIC"
__url__ = "" __url__ = ""
__doc__ = "Module for loading marker shapes for Lattice workbench" __doc__ = "Module for loading marker shapes for Lattice workbench"
_nullShapeShape = 0 _nullShapeShape = None
_ShapeDict = {} _ShapeDict = {}
_NodeDict = {}
def getShapePath(shapeName): def getShapePath(shapeName):
""" """
@ -44,7 +48,7 @@ def getNullShapeShape(scale = 1.0):
#read shape from file, if not done this before #read shape from file, if not done this before
global _nullShapeShape global _nullShapeShape
if not _nullShapeShape: if _nullShapeShape is None:
_nullShapeShape = Part.Shape() _nullShapeShape = Part.Shape()
f = open(getShapePath("empty-shape.brep")) f = open(getShapePath("empty-shape.brep"))
_nullShapeShape.importBrep(f) _nullShapeShape.importBrep(f)
@ -73,8 +77,7 @@ def loadShape(shapeID):
FreeCAD.Console.PrintError('Failed to load standard shape "'+shapeID+'". \n' + str(err) + '\n') FreeCAD.Console.PrintError('Failed to load standard shape "'+shapeID+'". \n' + str(err) + '\n')
sh = Part.Point() #Create at least something! sh = Part.Point() #Create at least something!
_ShapeDict[shapeID] = sh _ShapeDict[shapeID] = sh
return sh return sh
def getPlacementMarker(scale = 1.0, markerID = None): def getPlacementMarker(scale = 1.0, markerID = None):
'''getPlacementMarker(scale = 1.0, markerID = None): returns a placement marker shape. '''getPlacementMarker(scale = 1.0, markerID = None): returns a placement marker shape.
@ -87,3 +90,27 @@ def getPlacementMarker(scale = 1.0, markerID = None):
sh = sh.copy() sh = sh.copy()
sh.scale(scale) sh.scale(scale)
return sh return sh
def loadNode(shapeID):
global _NodeDict
nd = _NodeDict.get(shapeID)
if nd is None:
nd = CoinGlue.readNodeFromFile(getShapePath(shapeID + '.iv'))
_NodeDict[shapeID] = nd
nd.ref() # not sure if needed, but won't hurt.
return nd.copy()
def getRefPlmMarker(markerID, placement = None, scale = 1.0):
'''getRefPlmMarker(markerID, placement = None, scale = 1.0): returns a coin placement marker shape, as SoSeparator (+ transform node + shape node).
The shape is scaled according to "scale" argument.
markerID sets the marker file name.'''
sh = loadNode(markerID + '-refplm')
from pivy import coin
sep = coin.SoSeparator()
tr = coin.SoTransform()
if placement is not None:
CoinGlue.cointransform(placement, scale, tr)
sep.addChild(tr)
sep.addChild(sh)
return (sep, tr, sh)

View File

@ -33,7 +33,7 @@ import lattice2BaseFeature
import lattice2Executer import lattice2Executer
from lattice2ShapeCopy import shallowCopy, transformCopy_Smart from lattice2ShapeCopy import shallowCopy, transformCopy_Smart
from lattice2PopulateCopies import DereferenceArray from lattice2PopulateCopies import DereferenceArray, REF_MODES
class FeatureUnsupportedError(RuntimeError): class FeatureUnsupportedError(RuntimeError):
@ -182,7 +182,7 @@ class LatticePDPattern(object):
obj.addProperty('App::PropertyLink','PlacementsTo',"Lattice Pattern","Target placements") obj.addProperty('App::PropertyLink','PlacementsTo',"Lattice Pattern","Target placements")
obj.addProperty('App::PropertyEnumeration','Referencing',"Lattice Pattern","Reference placement mode (sets what to grab the feature by).") obj.addProperty('App::PropertyEnumeration','Referencing',"Lattice Pattern","Reference placement mode (sets what to grab the feature by).")
obj.Referencing = ['Origin','First item', 'Last item', 'Use PlacementsFrom'] obj.Referencing = REF_MODES
obj.addProperty('App::PropertyBool', 'IgnoreUnsupported', "Lattice Pattern", "Skip unsupported features such as fillets, instead of throwing errors") obj.addProperty('App::PropertyBool', 'IgnoreUnsupported', "Lattice Pattern", "Skip unsupported features such as fillets, instead of throwing errors")
obj.addProperty('App::PropertyBool', 'SkipFirstInBody', "Lattice Pattern", "Skip first body feature (which may be used as support for the important features).") obj.addProperty('App::PropertyBool', 'SkipFirstInBody', "Lattice Pattern", "Skip first body feature (which may be used as support for the important features).")
@ -250,8 +250,7 @@ class LatticePDPattern(object):
raise ScopeError('Reference placement and the feature are not in the same body (use Shapebinder or Ghost to bring the placement in).') raise ScopeError('Reference placement and the feature are not in the same body (use Shapebinder or Ghost to bring the placement in).')
placements = lattice2BaseFeature.getPlacementsList(selfobj.PlacementsTo, selfobj) placements = DereferenceArray(selfobj, selfobj.PlacementsTo, selfobj.PlacementsFrom, selfobj.Referencing)
placements = DereferenceArray(selfobj, placements, selfobj.PlacementsFrom, selfobj.Referencing)
if selfobj.Referencing == 'First item' and transforms is None: if selfobj.Referencing == 'First item' and transforms is None:
placements.pop(0) #to not repeat the feature where it was applied already placements.pop(0) #to not repeat the feature where it was applied already
elif selfobj.Referencing == 'Last item' and transforms is None: elif selfobj.Referencing == 'Last item' and transforms is None:

View File

@ -123,12 +123,16 @@ class LatticeParaSeries(lattice2BaseFeature.LatticeFeature):
self.generator.addProperties(groupname= "Lattice ParaSeries", self.generator.addProperties(groupname= "Lattice ParaSeries",
groupname_gen= "Lattice ParaSeries Generator", groupname_gen= "Lattice ParaSeries Generator",
valuesdoc= "List of parameter values to compute object for.") valuesdoc= "List of parameter values to compute object for.")
def updateReadonlyness(self, selfobj):
super(LatticeParaSeries, self).updateReadonlyness(selfobj)
self.assureGenerator(selfobj)
self.generator.updateReadonlyness() self.generator.updateReadonlyness()
def derivedExecute(self,selfobj): def derivedExecute(self,selfobj):
# values generator should be functional even if recomputing is disabled, so do it first # values generator should be functional even if recomputing is disabled, so do it first
self.assureGenerator(selfobj) self.assureGenerator(selfobj)
self.generator.updateReadonlyness()
self.generator.execute() self.generator.execute()
if selfobj.Recomputing == "Disabled": if selfobj.Recomputing == "Disabled":

View File

@ -75,8 +75,6 @@ class PolarArray(lattice2BaseFeature.LatticeFeature):
obj.EndInclusive = False obj.EndInclusive = False
obj.Count = 5 obj.Count = 5
self.assureProperties(obj)
def assureGenerator(self, obj): def assureGenerator(self, obj):
'''Adds an instance of value series generator, if one doesn't exist yet.''' '''Adds an instance of value series generator, if one doesn't exist yet.'''
if hasattr(self,"generator"): if hasattr(self,"generator"):
@ -89,21 +87,24 @@ class PolarArray(lattice2BaseFeature.LatticeFeature):
self.updateReadonlyness(obj) self.updateReadonlyness(obj)
def updateReadonlyness(self, obj): def updateReadonlyness(self, obj):
super(PolarArray, self).updateReadonlyness(obj)
axislink = screen(obj.AxisLink) axislink = screen(obj.AxisLink)
obj.setEditorMode("AxisDir", 1 if (axislink and obj.AxisDirIsDriven) else 0) obj.setEditorMode("AxisDir", 1 if (axislink and obj.AxisDirIsDriven) else 0)
obj.setEditorMode("AxisPoint", 1 if (axislink and obj.AxisPointIsDriven) else 0) obj.setEditorMode("AxisPoint", 1 if (axislink and obj.AxisPointIsDriven) else 0)
obj.setEditorMode("AxisDirIsDriven", 0 if axislink else 1) obj.setEditorMode("AxisDirIsDriven", 0 if axislink else 1)
obj.setEditorMode("AxisPointIsDriven", 0 if axislink else 1) obj.setEditorMode("AxisPointIsDriven", 0 if axislink else 1)
self.assureGenerator(obj)
self.generator.updateReadonlyness() self.generator.updateReadonlyness()
def assureProperties(self, selfobj): def assureProperties(self, selfobj, creating_new = False):
super(PolarArray, self).assureProperties(selfobj, creating_new)
assureProperty(selfobj, "App::PropertyLinkSub", "AxisSubLink", sublinkFromApart(screen(selfobj.AxisLink), selfobj.AxisLinkSubelement), "Lattice Array", "Mirror of Object+SubNames properties") assureProperty(selfobj, "App::PropertyLinkSub", "AxisSubLink", sublinkFromApart(screen(selfobj.AxisLink), selfobj.AxisLinkSubelement), "Lattice Array", "Mirror of Object+SubNames properties")
def derivedExecute(self,obj): def derivedExecute(self,obj):
self.assureGenerator(obj) self.assureGenerator(obj)
self.assureProperties(obj)
self.updateReadonlyness(obj)
# Apply links # Apply links
if screen(obj.AxisLink): if screen(obj.AxisLink):

View File

@ -45,7 +45,7 @@ V = App.Vector
def make(): def make():
'''make(): makes a PolarArray object.''' '''make(): makes a PolarArray object.'''
obj = lattice2BaseFeature.makeLatticeFeature('PolarArray', PolarArray, ViewProviderPolarArray, no_disable_attacher= True) obj = lattice2BaseFeature.makeLatticeFeature('PolarArray', PolarArray, ViewProviderPolarArray)
return obj return obj
def fetchArc(obj, sub): def fetchArc(obj, sub):
@ -85,7 +85,22 @@ class PolarArray(APlm.AttachableFeature):
selfobj.EndInclusive = False selfobj.EndInclusive = False
selfobj.Step = 55 selfobj.Step = 55
selfobj.Count = 7 selfobj.Count = 7
def assureProperties(self, selfobj, creating_new = False):
super(PolarArray, self).assureProperties(selfobj, creating_new)
# upgrades older versions of the feature
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'center', 'SpanStart', 'SpanEnd', 'at custom value', 'first placement', 'last placement'],
"Polar Array",
"Reference placement, corresponds to the original occurrence of the object to be populated."
)
if created:
selfobj.ReferencePlacementOption = 'SpanStart'
self.assureProperty(selfobj, 'App::PropertyFloat', 'ReferenceValue', 0.0, "Polar Array", "Sets the value to use for generating ReferencePlacement. This value sets, what angle the object to be populated corresponds to.")
def assureGenerator(self, selfobj): def assureGenerator(self, selfobj):
'''Adds an instance of value series generator, if one doesn't exist yet.''' '''Adds an instance of value series generator, if one doesn't exist yet.'''
if hasattr(self,'generator'): if hasattr(self,'generator'):
@ -95,13 +110,16 @@ class PolarArray(APlm.AttachableFeature):
groupname_gen= "Lattice Series Generator", groupname_gen= "Lattice Series Generator",
valuesdoc= "List of angles, in degrees.", valuesdoc= "List of angles, in degrees.",
valuestype= 'App::PropertyFloat') valuestype= 'App::PropertyFloat')
self.updateReadonlyness(selfobj)
def updateReadonlyness(self, selfobj): def updateReadonlyness(self, selfobj):
super(PolarArray, self).updateReadonlyness(selfobj)
self.assureGenerator(selfobj)
self.generator.updateReadonlyness() self.generator.updateReadonlyness()
arc = self.fetchArc(selfobj) arc = self.fetchArc(selfobj)
selfobj.setEditorMode('Radius', 1 if arc and selfobj.UseArcRadius else 0) selfobj.setEditorMode('Radius', 1 if arc and selfobj.UseArcRadius else 0)
selfobj.setEditorMode('ReferenceValue', 0 if selfobj.ReferencePlacementOption == 'at custom value' else 2)
self.generator.setPropertyWritable('SpanEnd', False if arc and selfobj.UseArcRange == 'as Span' else True) self.generator.setPropertyWritable('SpanEnd', False if arc and selfobj.UseArcRange == 'as Span' else True)
self.generator.setPropertyWritable('SpanStart', False if arc and selfobj.UseArcRange == 'as Span' else True) self.generator.setPropertyWritable('SpanStart', False if arc and selfobj.UseArcRange == 'as Span' else True)
self.generator.setPropertyWritable('Step', False if arc and selfobj.UseArcRange == 'as Step' else True) self.generator.setPropertyWritable('Step', False if arc and selfobj.UseArcRange == 'as Step' else True)
@ -113,6 +131,11 @@ class PolarArray(APlm.AttachableFeature):
sub = sub[0] sub = sub[0]
#resolve the link #resolve the link
return fetchArc(lnkobj, sub) return fetchArc(lnkobj, sub)
def recomputeReferencePlm(self, selfobj, selfplacements): #override
if selfobj.ReferencePlacementOption == 'external':
super(PolarArray, self).recomputeReferencePlm(selfobj, selfplacements)
#the remaining options are handled in derivedExecute
def derivedExecute(self,selfobj): def derivedExecute(self,selfobj):
self.assureGenerator(selfobj) self.assureGenerator(selfobj)
@ -189,7 +212,7 @@ class PolarArray(APlm.AttachableFeature):
angleplus = -90.0 if on_arc else 0.0 angleplus = -90.0 if on_arc else 0.0
mm = -1.0 if selfobj.Reverse else +1.0 mm = -1.0 if selfobj.Reverse else +1.0
output = [] # list of placements output = [] # list of placements
for ang in values: def plmByVal(ang):
localrot = App.Rotation(App.Vector(0,0,1), ang * mm + angleplus) localrot = App.Rotation(App.Vector(0,0,1), ang * mm + angleplus)
localtransl = localrot.multVec(App.Vector(radius,0,0)) localtransl = localrot.multVec(App.Vector(radius,0,0))
localplm = App.Placement(localtransl, localrot) localplm = App.Placement(localtransl, localrot)
@ -200,7 +223,29 @@ class PolarArray(APlm.AttachableFeature):
elif is_static: elif is_static:
resultplm.Rotation = App.Rotation() resultplm.Rotation = App.Rotation()
resultplm = resultplm.multiply(flipplm) resultplm = resultplm.multiply(flipplm)
output.append(resultplm) return resultplm
output = [plmByVal(ang) for ang in values]
# update reference placement
ref = selfobj.ReferencePlacementOption
if ref == 'external':
pass #gets done in recomputeReferencePlm
elif ref == 'origin':
self.setReferencePlm(selfobj, None)
elif ref == 'center':
self.setReferencePlm(selfobj, App.Placement())
elif ref == 'SpanStart':
self.setReferencePlm(selfobj, plmByVal(selfobj.SpanStart))
elif ref == 'SpanEnd':
self.setReferencePlm(selfobj, plmByVal(selfobj.SpanEnd))
elif ref == 'at custom value':
self.setReferencePlm(selfobj, plmByVal(selfobj.ReferenceValue))
elif ref == 'first placement':
self.setReferencePlm(selfobj, output[0])
elif ref == 'last placement':
self.setReferencePlm(selfobj, output[-1])
else:
raise NotImplementedError("Reference option not implemented: " + ref)
return output return output

View File

@ -34,7 +34,7 @@ from lattice2Common import *
import lattice2BaseFeature import lattice2BaseFeature
import lattice2CompoundExplorer as LCE import lattice2CompoundExplorer as LCE
import lattice2Executer import lattice2Executer
from lattice2PopulateCopies import DereferenceArray, throwBody from lattice2PopulateCopies import DereferenceArray, throwBody, REF_MODES
import lattice2ShapeCopy as ShapeCopy import lattice2ShapeCopy as ShapeCopy
# -------------------------- document object -------------------------------------------------- # -------------------------- document object --------------------------------------------------
@ -58,7 +58,7 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyBool","LoopObjectSequence","Lattice PopulateChildren","If true, children of Object will be traversed in a loop if there are more placements than children. Otherwise, extra placements will be dropped.") obj.addProperty("App::PropertyBool","LoopObjectSequence","Lattice PopulateChildren","If true, children of Object will be traversed in a loop if there are more placements than children. Otherwise, extra placements will be dropped.")
obj.addProperty("App::PropertyEnumeration","Referencing","Lattice PopulateChildren","Reference for array of placements.") obj.addProperty("App::PropertyEnumeration","Referencing","Lattice PopulateChildren","Reference for array of placements.")
obj.Referencing = ["Origin","First item", "Last item", "Use PlacementsFrom"] obj.Referencing = REF_MODES
obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateChildren", "Placement or array of placements, containing target locations.") obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateChildren", "Placement or array of placements, containing target locations.")
@ -88,11 +88,10 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
raise ValueError("Traversal mode not implemented: "+obj.ObjectTraversal) raise ValueError("Traversal mode not implemented: "+obj.ObjectTraversal)
else: else:
objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object), obj) objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object), obj)
placements = lattice2BaseFeature.getPlacementsList(screen(obj.PlacementsTo), obj)
# Precompute referencing # Precompute referencing
placements = DereferenceArray(obj, placements, screen(obj.PlacementsFrom), obj.Referencing) placements = DereferenceArray(obj, obj.PlacementsTo, screen(obj.PlacementsFrom), obj.Referencing)
# initialize output containers and loop variables # initialize output containers and loop variables
outputShapes = [] #output list of shapes outputShapes = [] #output list of shapes
@ -101,6 +100,20 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
numChildren = len(objectPlms) if outputIsLattice else len(objectShapes) numChildren = len(objectPlms) if outputIsLattice else len(objectShapes)
copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying) copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying)
#inherit reference placement from the array being copied
if outputIsLattice:
refplm = None
if obj.Referencing == 'Array\'s reference' or obj.Referencing == 'First item' or obj.Referencing == 'Last item':
#simple cases - we just copy the reference plm from the object
refplm = lattice2BaseFeature.getReferencePlm(obj.Object)
else:
#other cases - apply first transform to reference placement
refplm = lattice2BaseFeature.getReferencePlm(obj.Object)
if refplm is not None and len(placements) > 0:
refplm = placements[0].multiply(refplm)
self.setReferencePlm(obj, refplm)
# the essence # the essence
for iPlm in range(len(placements)): for iPlm in range(len(placements)):
if iChild == numChildren: if iChild == numChildren:
@ -176,6 +189,11 @@ def CreateLatticePopulateChildren(name, label, shapeObj, latticeObjFrom, lattice
FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name) FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name)
if latticeObjFrom is not None: if latticeObjFrom is not None:
FreeCADGui.doCommand("f.PlacementsFrom = App.ActiveDocument."+latticeObjFrom.Name) FreeCADGui.doCommand("f.PlacementsFrom = App.ActiveDocument."+latticeObjFrom.Name)
if refmode == 'Auto':
if lattice2BaseFeature.getReferencePlm(latticeObjTo) is not None:
refmode = 'Array\'s reference'
else:
refmode = 'First item'
FreeCADGui.doCommand("f.Referencing = "+repr(refmode)) FreeCADGui.doCommand("f.Referencing = "+repr(refmode))
FreeCADGui.doCommand("f.Label = " + repr(label)) FreeCADGui.doCommand("f.Label = " + repr(label))

View File

@ -37,13 +37,16 @@ import lattice2Executer
import lattice2ShapeCopy as ShapeCopy import lattice2ShapeCopy as ShapeCopy
# ---------------------------shared code-------------------------------------- # ---------------------------shared code--------------------------------------
def DereferenceArray(obj,placements, lnkFrom, refmode):
REF_MODES = ['Origin', 'First item', 'Last item', 'Use PlacementsFrom', 'Array\'s reference']
def DereferenceArray(obj, lnkTo, lnkFrom, refmode):
'''common implementation of treatment Referencing property. Returns a list of placements to use directly. '''common implementation of treatment Referencing property. Returns a list of placements to use directly.
obj - feature being executed (used for error reporting; can be None) obj - feature being executed
placements - the array, converted into a list of placements. lnkTo - the array of target placements (documentobject).
lnkFrom - object linked as a lattice of 'from' placements. Can be None, if mode is not 'Use PlacemenetsFrom' lnkFrom - object linked as a lattice of 'from' placements. Can be None, if mode is not 'Use PlacemenetsFrom'
refmode - a string - enum property item''' refmode - a string - enum property item'''
placements = lattice2BaseFeature.getPlacementsList(lnkTo, obj)
plmDeref = App.Placement() #inverse placement of reference (reference is a substitute of origin) plmDeref = App.Placement() #inverse placement of reference (reference is a substitute of origin)
if lnkFrom is not None and refmode != "Use PlacementsFrom": if lnkFrom is not None and refmode != "Use PlacementsFrom":
lattice2Executer.warning(obj,"Referencing mode is '"+refmode+"', doesn't need PlacementsFrom link to be set. The link is set, but it will be ignored.") lattice2Executer.warning(obj,"Referencing mode is '"+refmode+"', doesn't need PlacementsFrom link to be set. The link is set, but it will be ignored.")
@ -52,7 +55,7 @@ def DereferenceArray(obj,placements, lnkFrom, refmode):
elif refmode == "First item": elif refmode == "First item":
plmDeref = placements[0].inverse() plmDeref = placements[0].inverse()
elif refmode == "Last item": elif refmode == "Last item":
plmDeref = placements[0].inverse() plmDeref = placements[-1].inverse()
elif refmode == "Use PlacementsFrom": elif refmode == "Use PlacementsFrom":
if lnkFrom is None: if lnkFrom is None:
raise ValueError("Referencing mode is 'Move from to', but PlacementsFrom link is not set.") raise ValueError("Referencing mode is 'Move from to', but PlacementsFrom link is not set.")
@ -63,8 +66,13 @@ def DereferenceArray(obj,placements, lnkFrom, refmode):
return [lattice2BaseFeature.makeMoveFromTo(placementsFrom[i], placements[i]) for i in range(0, len(placements))] return [lattice2BaseFeature.makeMoveFromTo(placementsFrom[i], placements[i]) for i in range(0, len(placements))]
else: else:
lattice2Executer.warning(obj,"Lengths of arrays linked as PlacementsTo and PlacementsFrom must equal, or PlacementsFrom can be one placement. Violation: lengths are "+str(len(placements))+ " and "+str(len(placementsFrom))) lattice2Executer.warning(obj,"Lengths of arrays linked as PlacementsTo and PlacementsFrom must equal, or PlacementsFrom can be one placement. Violation: lengths are "+str(len(placements))+ " and "+str(len(placementsFrom)))
elif refmode == 'Array\'s reference':
plmRef = lattice2BaseFeature.getReferencePlm(lnkTo)
if plmRef is None:
raise AttributeError('Object {obj} does not expose a reference placement.')
plmDeref = plmRef.inverse()
else: else:
raise ValueError("Referencing mode not implemented: "+refmode) raise ValueError("Referencing mode not implemented: " + refmode)
return [plm.multiply(plmDeref) for plm in placements] return [plm.multiply(plmDeref) for plm in placements]
@ -85,40 +93,54 @@ class LatticePopulateCopies(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyLink","Object","Lattice PopulateCopies","Base object. Can be any generic shape, as well as another lattice object.") obj.addProperty("App::PropertyLink","Object","Lattice PopulateCopies","Base object. Can be any generic shape, as well as another lattice object.")
obj.addProperty("App::PropertyEnumeration","Referencing","Lattice PopulateCopies","Reference for array of placements.") obj.addProperty("App::PropertyEnumeration","Referencing","Lattice PopulateCopies","Reference for array of placements.")
obj.Referencing = ["Origin","First item", "Last item", "Use PlacementsFrom"] obj.Referencing = REF_MODES
obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateCopies", "Placement or array of placements, containing target locations.") obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateCopies", "Placement or array of placements, containing target locations.")
obj.addProperty("App::PropertyLink","PlacementsFrom", "Lattice PopulateCopies","Placement or array of placements to be treated as origins for PlacementsTo.") obj.addProperty("App::PropertyLink","PlacementsFrom", "Lattice PopulateCopies","Placement or array of placements to be treated as origins for PlacementsTo.")
self.assureProperties(obj)
obj.OutputCompounding = "(autosettle)" # this is default value for new features.
def assureProperties(self, obj): def assureProperties(self, obj, creating_new = False):
'''Adds properties that might be missing, because of loaded project made with older version. Handles version compatibility.''' '''Adds properties that might be missing, because of loaded project made with older version. Handles version compatibility.'''
super(LatticePopulateCopies, self).assureProperties(obj, creating_new)
propname = 'OutputCompounding' propname = 'OutputCompounding'
if not hasattr(obj,propname): if not hasattr(obj,propname):
obj.addProperty("App::PropertyEnumeration", propname, "Lattice PopulateCopies","In case single object copy is made, this property controls, if it's packed into compoud or not.") obj.addProperty("App::PropertyEnumeration", propname, "Lattice PopulateCopies","In case single object copy is made, this property controls, if it's packed into compoud or not.")
setattr(obj,propname,["(autosettle)","always", "only if many"]) setattr(obj,propname,["(autosettle)","always", "only if many"])
setattr(obj,propname,"always") # this is to match the old behavior. This is not the default setting for new features. if creating_new:
obj.OutputCompounding = "(autosettle)" # this is default value for new features.
else:
setattr(obj,propname,"always") # this is to match the old behavior. This is not the default setting for new features.
if self.assureProperty(obj, "App::PropertyEnumeration","Copying", ShapeCopy.copy_types, "Lattice PopulateChildren", "Sets, what method to use for copying shapes."): if self.assureProperty(obj, "App::PropertyEnumeration","Copying", ShapeCopy.copy_types, "Lattice PopulateChildren", "Sets, what method to use for copying shapes."):
self.Copying = ShapeCopy.copy_types[0] self.Copying = ShapeCopy.copy_types[0]
def derivedExecute(self,obj): def derivedExecute(self,obj):
self.assureProperties(obj)
# cache stuff # cache stuff
objectShape = screen(obj.Object).Shape objectShape = screen(obj.Object).Shape
placements = lattice2BaseFeature.getPlacementsList(screen(obj.PlacementsTo), obj)
outputIsLattice = lattice2BaseFeature.isObjectLattice(screen(obj.Object)) outputIsLattice = lattice2BaseFeature.isObjectLattice(screen(obj.Object))
# Pre-collect base placement list, if base is a lattice. For speed. # Pre-collect base placement list, if base is a lattice. For speed.
if outputIsLattice: if outputIsLattice:
objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object),obj) objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object),obj)
placements = DereferenceArray(obj, placements, screen(obj.PlacementsFrom), obj.Referencing) placements = DereferenceArray(obj, obj.PlacementsTo, screen(obj.PlacementsFrom), obj.Referencing)
#inherit reference placement from the array being copied
if outputIsLattice:
refplm = None
if obj.Referencing == 'Array\'s reference' or obj.Referencing == 'First item' or obj.Referencing == 'Last item':
#simple cases - we just copy the reference plm from the object
refplm = lattice2BaseFeature.getReferencePlm(obj.Object)
else:
#other cases - apply first transform to reference placement
refplm = lattice2BaseFeature.getReferencePlm(obj.Object)
if refplm is not None and len(placements) > 0:
refplm = placements[0].multiply(refplm)
self.setReferencePlm(obj, refplm)
# initialize output containers and loop variables # initialize output containers and loop variables
outputShapes = [] #output list of shapes outputShapes = [] #output list of shapes
@ -161,18 +183,20 @@ class ViewProviderLatticePopulateCopies(lattice2BaseFeature.ViewProviderLatticeF
def getIcon(self): def getIcon(self):
if lattice2BaseFeature.isObjectLattice(self.Object): if lattice2BaseFeature.isObjectLattice(self.Object):
return getIconPath( return getIconPath(
{"Origin":"Lattice2_PopulateCopies_Plms_Normal.svg", {'Origin':'Lattice2_PopulateCopies_Plms_Normal.svg',
"First item":"Lattice2_PopulateCopies_Plms_Array.svg", 'First item':'Lattice2_PopulateCopies_Plms_Array.svg',
"Last item":"Lattice2_PopulateCopies_Plms_Array.svg", 'Last item':'Lattice2_PopulateCopies_Plms_Array.svg',
"Use PlacementsFrom":"Lattice2_PopulateCopies_Plms_Move.svg", 'Use PlacementsFrom':'Lattice2_PopulateCopies_Plms_Move.svg',
'Array\'s reference':'Lattice2_PopulateCopies_Plms_Ref.svg',
}[self.Object.Referencing] }[self.Object.Referencing]
) )
else: else:
return getIconPath( return getIconPath(
{"Origin":"Lattice2_PopulateCopies_Normal.svg", {'Origin':'Lattice2_PopulateCopies_Normal.svg',
"First item":"Lattice2_PopulateCopies_Array.svg", 'First item':'Lattice2_PopulateCopies_Array.svg',
"Last item":"Lattice2_PopulateCopies_Array.svg", 'Last item':'Lattice2_PopulateCopies_Array.svg',
"Use PlacementsFrom":"Lattice2_PopulateCopies_Move.svg", 'Use PlacementsFrom':'Lattice2_PopulateCopies_Move.svg',
'Array\'s reference':'Lattice2_PopulateCopies_Ref.svg',
}[self.Object.Referencing] }[self.Object.Referencing]
) )
@ -199,6 +223,11 @@ def CreateLatticePopulateCopies(name, label, shapeObj, latticeObjFrom, latticeOb
FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name) FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name)
if latticeObjFrom is not None: if latticeObjFrom is not None:
FreeCADGui.doCommand("f.PlacementsFrom = App.ActiveDocument."+latticeObjFrom.Name) FreeCADGui.doCommand("f.PlacementsFrom = App.ActiveDocument."+latticeObjFrom.Name)
if refmode == 'Auto':
if lattice2BaseFeature.getReferencePlm(latticeObjTo) is not None:
refmode = 'Array\'s reference'
else:
refmode = 'First item'
FreeCADGui.doCommand("f.Referencing = "+repr(refmode)) FreeCADGui.doCommand("f.Referencing = "+repr(refmode))
FreeCADGui.doCommand("f.Label = " + repr(label)) FreeCADGui.doCommand("f.Label = " + repr(label))
@ -220,72 +249,83 @@ def CreateLatticePopulateCopies(name, label, shapeObj, latticeObjFrom, latticeOb
def throwBody(): def throwBody():
raise SelectionError("PartDesign mode", "You can't use population tools on shapes in partdesign body. Use Lattice PartDesign Pattern instead. Or deactivate active body to use populate tools on shapes.") raise SelectionError("PartDesign mode", "You can't use population tools on shapes in partdesign body. Use Lattice PartDesign Pattern instead. Or deactivate active body to use populate tools on shapes.")
def cmdPopulate_shapes_nonFromTo(refmode): def cmdPopulateCopies():
sel = FreeCADGui.Selection.getSelectionEx() sel = FreeCADGui.Selection.getSelectionEx()
(lattices, shapes) = lattice2BaseFeature.splitSelection(sel) (lattices, shapes) = lattice2BaseFeature.splitSelection(sel)
if activeBody() and len(shapes)>0: if activeBody() and len(shapes)>0:
throwBody() throwBody()
if len(shapes) > 0 and len(lattices) == 1:
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
lattice = lattices[0]
for shape in shapes:
CreateLatticePopulateCopies("Populate",u"Populate "+lattice.Object.Label+u" with "+shape.Object.Label,shape.Object,None,lattice.Object,refmode)
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
elif len(shapes) == 1 and len(lattices) > 1:
shape = shapes[0]
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
for lattice in lattices:
CreateLatticePopulateCopies("Populate",u"Populate "+lattice.Object.Label+u" with "+shape.Object.Label,shape.Object,None,lattice.Object,refmode)
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
elif len(shapes) == 0 and len(lattices) == 2:
shape = lattices[0]
lattice = lattices[1]
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
CreateLatticePopulateCopies("Populate",u"Populate "+lattice.Object.Label+u" with "+shape.Object.Label,shape.Object,None,lattice.Object,refmode)
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
else:
raise SelectionError("Bad selection","Please select some shapes and some arrays, first. You can select multiple shapes and one array, or multiple arrays and one shape.")
def cmdPopulate_shapes_FromTo():
sel = FreeCADGui.Selection.getSelectionEx()
(lattices, shapes) = lattice2BaseFeature.splitSelection(sel)
if activeBody() and len(shapes)>0:
throwBody()
if len(shapes) == 0 and len(sel) >= 3:
shapes = sel[:-2]
lattices = sel[-2:]
if len(shapes) > 0 and len(lattices) == 2: if len(shapes) > 0 and len(lattices) == 2:
FreeCAD.ActiveDocument.openTransaction("Populate with copies") # move shapes from to
FreeCAD.ActiveDocument.openTransaction("Transport")
latticeFrom = lattices[0] latticeFrom = lattices[0]
latticeTo = lattices[1] latticeTo = lattices[1]
for shape in shapes: for shape in shapes:
CreateLatticePopulateCopies("Populate",u"Moved "+shape.Object.Label, shape.Object, latticeFrom.Object, latticeTo.Object,"Use PlacementsFrom") CreateLatticePopulateCopies("Populate",u"Moved "+shape.Object.Label, shape.Object, latticeFrom.Object, latticeTo.Object,'Use PlacementsFrom')
deselect(sel) deselect(sel)
FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.commitTransaction()
elif len(shapes) == 0 and len(lattices) == 3:
# move array from to
FreeCAD.ActiveDocument.openTransaction("Transport")
shape = lattices[0]
latticeFrom = lattices[1]
latticeTo = lattices[2]
for shape in shapes:
CreateLatticePopulateCopies("Populate",u"Moved "+shape.Object.Label, shape.Object, latticeFrom.Object, latticeTo.Object,'Use PlacementsFrom')
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
elif len(shapes) > 0 and len(lattices) == 1:
# populate shapes
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
lattice = lattices[0]
for shape in shapes:
CreateLatticePopulateCopies("Populate",u"Populate "+lattice.Object.Label+u" with "+shape.Object.Label,shape.Object,None,lattice.Object,'Auto')
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
elif len(shapes) == 0 and (len(lattices) == 2 or len(lattices) > 3):
# populate placements
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
shapes = lattices[:-1]
lattice = lattices[-1]
for shape in shapes:
CreateLatticePopulateCopies("Populate",u"Populate "+lattice.Object.Label+u" with "+shape.Object.Label, shape.Object, None, lattice.Object,'Auto')
deselect(sel)
FreeCAD.ActiveDocument.commitTransaction()
else: else:
raise SelectionError("Bad selection","Please select either:\n one or more shapes, and two placements/arrays \nor\nthree placements/arrays") raise SelectionError("Bad selection",
"You selected {n_lattices} arrays of placements and {n_shapes} shapes. This is not supported.\n\n"
"You can select:\n"
" * N shapes and 1 array, to populate that array with the shapes\n"
" * N shapes and 2 arrays, to move shapes from array1 to array2\n"
" * 2 arrays, to populate array2 with array1\n"
" * 3 arrays, to move array1 from array2 to array3\n"
" * 4 or more arrays, to populate last array with all other arrays"
.format(n_lattices= len(lattices), n_shapes= len(shapes))
)
class _CommandLatticePopulateCopies_Normal: class CommandLatticePopulateCopies:
"Command to create LatticePopulateCopies feature" "Command to create LatticePopulateCopies feature"
def GetResources(self): def GetResources(self):
return {'Pixmap' : getIconPath("Lattice2_PopulateCopies_Normal.svg"), return {'Pixmap' : getIconPath("Lattice2_PopulateCopies.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Populate with copies"), 'MenuText': "Populate with copies",
'Accel': "", 'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Populate with copies: put copies of an object at every placement in an array. Select the object(s) to be copied, and the placement/array.")} 'ToolTip': "Populate with copies: put copies of an object at every placement in an array. Select the object(s) to be copied, and the placement/array."}
def Activated(self): def Activated(self):
try: try:
if len(FreeCADGui.Selection.getSelection())==0: if len(FreeCADGui.Selection.getSelection())==0:
infoMessage("Populate with copies", infoMessage("Populate with copies",
"Populate with copies command. Places a copy of a selected object placed under selected placement.\n\n"+ "Populate with copies command. Places a copy of a selected object at every placement in an array of placements.\n\n"+
"Please select some objects, and a placement/an array of placements. Then invoke the command.\n\n"+ "Please select some objects, and a placement/an array of placements. Then invoke the command.\n\n"+
"A copy of object will pe made and placed in local coordinate system of each placement in an array. Placement of the object is taken into account, and becomes a placement in local coordinates of a placement of the array item.") "You can select:\n"
" * N shapes and 1 array, to populate that array with the shapes\n"
" * N shapes and 2 arrays, to move shapes from array1 to array2\n"
" * 2 arrays, to populate array2 with array1\n"
" * 3 arrays, to move array1 from array2 to array3\n"
" * 4 or more arrays, to populate last array with all other arrays"
)
return return
cmdPopulate_shapes_nonFromTo("Origin") cmdPopulateCopies()
except Exception as err: except Exception as err:
msgError(err) msgError(err)
@ -296,85 +336,9 @@ class _CommandLatticePopulateCopies_Normal:
return False return False
if FreeCAD.GuiUp: if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2_PopulateCopies_Normal', _CommandLatticePopulateCopies_Normal()) FreeCADGui.addCommand('Lattice2_PopulateCopies', CommandLatticePopulateCopies())
class _CommandLatticePopulateCopies_Array: exportedCommands = ['Lattice2_PopulateCopies']
"Command to create LatticePopulateCopies feature"
def GetResources(self):
return {'Pixmap' : getIconPath("Lattice2_PopulateCopies_Array.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Populate with copies: Build Array"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Populate with copies: Build Array: poplate placements with copies so that the array passes through original shape. Select the object(s) to be copied, and the placement/array.")}
def Activated(self):
try:
if len(FreeCADGui.Selection.getSelection())==0:
infoMessage("Populate with copies: Build Array",
"Populate with copies: Build Array command. Creates an array of shapes.\n\n"+
"Please select some objects, and the array of placements. Then invoke the command. Object can also be a placement/array.\n\n"+
"Compared to plain 'Populate With copies' command, the placements are treated as being relative to the first placement in the array. As a result, the array built always includes the original object as-is.")
return
cmdPopulate_shapes_nonFromTo("First item")
except Exception as err:
msgError(err)
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2_PopulateCopies_Array', _CommandLatticePopulateCopies_Array())
class _CommandLatticePopulateCopies_Move:
"Command to create LatticePopulateCopies feature"
def GetResources(self):
return {'Pixmap' : getIconPath("Lattice2_PopulateCopies_Move.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Moved object"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Moved object: move object from one placement to another placement. Select the object, placement to move from, and placement to move to. Arrays of placements are accepted.")}
def Activated(self):
try:
if len(FreeCADGui.Selection.getSelection())==0:
infoMessage("Moved Object",
"Moved Object command. Creates a moved copy of a shape.\n\n"+
"The shape is moved from one placement to another placement. Please select some shapes, then placement to move from, and placement to move to (order matters).\n"+
"Placement 'to' can be an array of placements; the array of objects will be created in this case. If 'to' is an array, 'from' can be either a single placement, or an array of matching length.\n\n"+
"Object can itself be an array of placements.")
return
cmdPopulate_shapes_FromTo()
except Exception as err:
msgError(err)
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2_PopulateCopies_Move', _CommandLatticePopulateCopies_Move())
class _CommandLatticePopulateCopiesGroup:
def GetCommands(self):
return ("Lattice2_PopulateCopies_Normal","Lattice2_PopulateCopies_Array","Lattice2_PopulateCopies_Move")
def GetDefaultCommand(self): # return the index of the tuple of the default command.
return 0
def GetResources(self):
return { 'MenuText': 'Populate with copies:',
'ToolTip': 'Populate with copies: put a copy of an object at every placement in an array of placements.'}
def IsActive(self): # optional
return True
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2_PopulateCopiesGroupCommand',_CommandLatticePopulateCopiesGroup())
exportedCommands = ['Lattice2_PopulateCopiesGroupCommand']
# -------------------------- /Gui command -------------------------------------------------- # -------------------------- /Gui command --------------------------------------------------

View File

@ -64,22 +64,38 @@ class LatticeProjectArray(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyEnumeration","Multisolution","Lattice ProjectArray","Specify the way of dealing with multiple solutions of projection") obj.addProperty("App::PropertyEnumeration","Multisolution","Lattice ProjectArray","Specify the way of dealing with multiple solutions of projection")
obj.Multisolution = ['use first','use all'] obj.Multisolution = ['use first','use all']
def assureProperties(self, selfobj, creating_new = False):
super(LatticeProjectArray, self).assureProperties(selfobj, creating_new)
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'inherit', 'projected'],
"Lattice ProjectArray",
"Reference placement, corresponds to the original occurrence of the object to be populated."
)
if created:
selfobj.ReferencePlacementOption = 'inherit'
def recomputeReferencePlm(self, selfobj, selfplacements): #override
if selfobj.ReferencePlacementOption == 'external':
super(LinearProjectArray, self).recomputeReferencePlm(selfobj, selfplacements)
#the remaining options are handled in derivedExecute
def derivedExecute(self,obj): def derivedExecute(self,obj):
#validity check
if not lattice2BaseFeature.isObjectLattice(screen(obj.Base)):
lattice2Executer.warning(obj,"A lattice object is expected as Base, but a generic shape was provided. It will be treated as a lattice object; results may be unexpected.")
toolShape = screen(obj.Tool).Shape toolShape = screen(obj.Tool).Shape
if lattice2BaseFeature.isObjectLattice(screen(obj.Tool)): if lattice2BaseFeature.isObjectLattice(screen(obj.Tool)):
lattice2Executer.warning(obj,"A lattice object was provided as Tool. It will be converted into points; orientations will be ignored.") lattice2Executer.warning(obj, "A lattice object was provided as Tool. It will be converted into points; orientations will be ignored.")
leaves = LCE.AllLeaves(toolShape) plms = lattice2BaseFeature.getPlacementsList(obj.Tool)
points = [Part.Vertex(leaf.Placement.Base) for leaf in leaves] points = [Part.Vertex(plm.Base) for plm in plms]
toolShape = Part.makeCompound(points) toolShape = Part.makeCompound(points)
leaves = LCE.AllLeaves(screen(obj.Base).Shape) ref = obj.ReferencePlacementOption
input = [leaf.Placement for leaf in leaves]
input = lattice2BaseFeature.getPlacementsList(obj.Base, obj)
if ref == 'projected':
input.append(lattice2BaseFeature.getReferencePlm(obj.Base))
output = [] #variable to receive the final list of placements output = [] #variable to receive the final list of placements
@ -170,6 +186,17 @@ class LatticeProjectArray(lattice2BaseFeature.LatticeFeature):
if not isMultiSol: if not isMultiSol:
break break
if ref == 'external':
pass
elif ref == 'origin':
self.setReferencePlm(obj, None)
elif ref == 'inherit':
self.setReferencePlm(obj, lattice2BaseFeature.getReferencePlm(obj.Base))
elif ref == 'projected':
self.setReferencePlm(obj, output.pop())
else:
raise NotImplementedError("Reference option not implemented: " + ref)
return output return output
@ -189,7 +216,7 @@ def CreateLatticeProjectArray(name):
iLtc = 0 #index of lattice object in selection iLtc = 0 #index of lattice object in selection
iStc = 1 #index of stencil object in selection iStc = 1 #index of stencil object in selection
for i in range(0,len(sel)): for i in range(0,len(sel)):
if lattice2BaseFeature.isObjectLattice(sel[i]): if lattice2BaseFeature.isObjectLattice(sel[i].Object):
iLtc = i iLtc = i
iStc = i-1 #this may give negative index, but python accepts negative indexes iStc = i-1 #this may give negative index, but python accepts negative indexes
break break

257
lattice2Resample2.py Normal file
View File

@ -0,0 +1,257 @@
#***************************************************************************
#* *
#* Copyright (c) 2018 - Victor Titov (DeepSOIC) *
#* <vv.titov@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
__title__="Lattice Resample object: changes the number of placements in an array, maintaining overall path. Aka interpolation."
__author__ = "DeepSOIC"
__url__ = ""
import FreeCAD as App
import Part
from lattice2Common import *
import lattice2BaseFeature
import lattice2InterpolatorUtil as LIU
import lattice2Executer
from lattice2ValueSeriesGenerator import ValueSeriesGenerator
# -------------------------- document object --------------------------------------------------
def dotProduct(list1,list2):
sum = 0
for i in range(0,len(list1)):
sum += list1[i]*list2[i]
return sum
def makeLatticeResample(name):
'''makeLatticeResample(name): makes a LatticeResample object.'''
return lattice2BaseFeature.makeLatticeFeature(name, LatticeResample, ViewProviderLatticeResample)
class LatticeResample(lattice2BaseFeature.LatticeFeature):
"The Lattice Resample object"
def derivedInit(self,selfobj):
selfobj.addProperty("App::PropertyLink","Base","Lattice Resample","Lattice, the array of placements to be interpolated.")
selfobj.addProperty("App::PropertyEnumeration","TranslateMode","Lattice Resample","What to do with translation part of placements")
selfobj.TranslateMode = ['interpolate', 'reset']
selfobj.TranslateMode = 'interpolate'
selfobj.addProperty("App::PropertyEnumeration","OrientMode","Lattice Resample","what to do with orientation part of placements")
selfobj.OrientMode = ['interpolate', 'reset']
selfobj.OrientMode = 'interpolate'
self.assureGenerator(selfobj)
selfobj.ValuesSource = "Generator"
selfobj.GeneratorMode = "SpanN"
selfobj.EndInclusive = True
selfobj.SpanStart = 0.0
selfobj.SpanEnd = 1.0
selfobj.Step = 1.0/51.0
selfobj.Count = 51
def assureProperties(self, selfobj, creating_new = False):
super(LatticeResample, self).assureProperties(selfobj, creating_new)
created = self.assureProperty(selfobj,
'App::PropertyEnumeration',
'ReferencePlacementOption',
['external', 'origin', 'inherit', 'SpanStart', 'SpanEnd', 'at custom value', 'first placement', 'last placement'],
"Lattice Resample",
"Reference placement, corresponds to the original occurrence of the object to be populated."
)
if created:
selfobj.ReferencePlacementOption = 'SpanStart'
self.assureProperty(selfobj, 'App::PropertyFloat', 'ReferenceValue', 0.0, "Lattice Resample", "Sets the value to use for generating ReferencePlacement. This value sets, what coordinate the object to be populated corresponds to.")
def assureGenerator(self, selfobj):
'''Adds an instance of value series generator, if one doesn't exist yet.'''
if hasattr(self,"generator"):
return
self.generator = ValueSeriesGenerator(selfobj)
self.generator.addProperties(groupname= "Lattice Array",
groupname_gen= "Lattice Series Generator",
valuesdoc= "List of parameter values. Values should be in range 0..n-1 for interpolation, and can be outside for extrapolation.",
valuestype= "App::PropertyFloat")
def updateReadonlyness(self, selfobj):
super(LatticeResample, self).updateReadonlyness(selfobj)
self.assureGenerator(selfobj)
self.generator.updateReadonlyness()
selfobj.setEditorMode('ReferenceValue', 0 if selfobj.ReferencePlacementOption == 'at custom value' else 2)
def recomputeReferencePlm(self, selfobj, selfplacements): #override
if selfobj.ReferencePlacementOption == 'external':
super(LatticeResample, self).recomputeReferencePlm(selfobj, selfplacements)
#the remaining options are handled in derivedExecute
def derivedExecute(self,selfobj):
self.assureGenerator(selfobj)
self.generator.execute()
values = [float(strv) for strv in selfobj.Values]
input = lattice2BaseFeature.getPlacementsList(selfobj.Base)
if len(input) < 2:
raise ValueError("At least 2 placements ar needed to interpolate; there are just "+str(len(input))+" in base array.")
#cache mode comparisons, for speed
posIsInterpolate = selfobj.TranslateMode == 'interpolate'
posIsReset = selfobj.TranslateMode == 'reset'
oriIsInterpolate = selfobj.OrientMode == 'interpolate'
oriIsReset = selfobj.OrientMode == 'reset'
# construct interpolation functions
# prepare lists of input samples
IArray = [float(i) for i in range(0,len(input))]
XArray = [plm.Base.x for plm in input]
YArray = [plm.Base.y for plm in input]
ZArray = [plm.Base.z for plm in input]
QArrays = [[],[],[],[]]
prevQ = [0.0]*4
for plm in input:
Q = plm.Rotation.Q
#test if quaernion has changed sign compared to previous one.
# Quaternions of opposite sign are equivalent in terms of rotation,
# but sign changes confuse interpolation, so we are detecting sign
# changes and discarding them
if dotProduct(Q,prevQ) < -ParaConfusion:
Q = [-v for v in Q]
for iQ in [0,1,2,3]:
QArrays[iQ].append( Q[iQ] )
prevQ = Q
# constuct function objects
if posIsInterpolate:
FX = LIU.InterpolateF(IArray,XArray)
FY = LIU.InterpolateF(IArray,YArray)
FZ = LIU.InterpolateF(IArray,ZArray)
if oriIsInterpolate:
FQs = []
for iQ in [0,1,2,3]:
FQs.append(LIU.InterpolateF(IArray,QArrays[iQ]))
def plmByVal(val):
pos = App.Vector()
ori = App.Rotation()
if posIsInterpolate:
pos = App.Vector(FX.value(val), FY.value(val), FZ.value(val))
if oriIsInterpolate:
ori = App.Rotation(FQs[0].value(val),
FQs[1].value(val),
FQs[2].value(val),
FQs[3].value(val))
return App.Placement(pos, ori)
output = [plmByVal(val) for val in values]
# update reference placement
ref = selfobj.ReferencePlacementOption
if ref == 'external':
pass
elif ref == 'origin':
self.setReferencePlm(selfobj, None)
elif ref == 'inherit':
self.setReferencePlm(selfobj, lattice2BaseFeature.getReferencePlm(selfobj.Base))
elif ref == 'SpanStart':
self.setReferencePlm(selfobj, plmByVal(float(selfobj.SpanStart)))
elif ref == 'SpanEnd':
self.setReferencePlm(selfobj, plmByVal(float(selfobj.SpanEnd)))
elif ref == 'at custom value':
self.setReferencePlm(selfobj, plmByVal(float(selfobj.ReferenceValue)))
elif ref == 'first placement':
self.setReferencePlm(selfobj, output[0])
elif ref == 'last placement':
self.setReferencePlm(selfobj, output[-1])
else:
raise NotImplementedError("Reference option not implemented: " + ref)
return output
class ViewProviderLatticeResample(lattice2BaseFeature.ViewProviderLatticeFeature):
def getIcon(self):
return getIconPath('Lattice2_Resample.svg')
def claimChildren(self):
return [screen(self.Object.Base)]
# -------------------------- /document object --------------------------------------------------
# -------------------------- Gui command --------------------------------------------------
def CreateLatticeResample(name):
sel = FreeCADGui.Selection.getSelectionEx()
FreeCAD.ActiveDocument.openTransaction("Create LatticeResample")
FreeCADGui.addModule("lattice2Resample2")
FreeCADGui.addModule("lattice2Executer")
FreeCADGui.doCommand("f = lattice2Resample2.makeLatticeResample(name='"+name+"')")
FreeCADGui.doCommand("f.Base = App.ActiveDocument."+sel[0].ObjectName)
FreeCADGui.doCommand("f.setExpression('SpanEnd', '{base}.NumElements - 1')".format(base= lattice2BaseFeature.source(sel[0].Object)[1].Name))
FreeCADGui.doCommand("for child in f.ViewObject.Proxy.claimChildren():\n"+
" child.ViewObject.hide()")
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
FreeCADGui.doCommand("f = None")
FreeCAD.ActiveDocument.commitTransaction()
class _CommandLatticeResample:
"Command to create LatticeResample feature"
def GetResources(self):
return {'Pixmap' : getIconPath("Lattice2_Resample.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_Resample","Resample Array"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_Resample","Lattice Resample: interpolate placement-path using 3-rd degree b-spline interpolation.")}
def Activated(self):
try:
if len(FreeCADGui.Selection.getSelection()) == 1 :
CreateLatticeResample(name = "Resample")
else:
infoMessage(
"Lattice Resample command. Interpolates an array of placements, using 3-rd dergee bsplines.\n\n"
"Please select one object, first. The object must be an array of placements."
)
except Exception as err:
msgError(err)
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2_Resample2', _CommandLatticeResample())
exportedCommands = ['Lattice2_Resample2']
# -------------------------- /Gui command --------------------------------------------------

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,149 @@
#Inventor V2.1 ascii
PickStyle {
style UNPICKABLE
}
Coordinate3 {
point [ 2.4286127e-017 2.3747374e-017 0,
1 0 0,
-0.28144613 -0.48747897 0,
2.4286127e-017 2.3747374e-017 0,
-0.28144613 0.48747897 0,
1 0 0,
2.4286127e-017 2.3747374e-017 0,
1 0 0,
0 -6.3415941e-017 -0.28560001,
2.4286127e-017 2.3747374e-017 0,
1 0 0,
-0.28144613 -0.48747897 0,
-0.28144613 0.48747897 0,
0 -6.3415941e-017 -0.28560001 ]
}
Switch {
whichChild 0
Separator {
DEF myLines Separator {
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0.33333334 0.65490198 0.87058824
specularColor 0 0 0
emissiveColor 0 0 0
shininess 1
transparency 0
}
DrawStyle {
style LINES
lineWidth 2
linePattern 0xffff
}
SoBrepEdgeSet {
fields [ SFNode vertexProperty, MFInt32 coordIndex, MFInt32 materialIndex, MFInt32 normalIndex, MFInt32 textureCoordIndex, SFInt32 highlightIndex, MFInt32 selectionIndex ]
coordIndex [ 0, 1, -1, 1, 2, -1, 2, 0,
-1, 3, 4, -1, 4, 5, -1, 8,
6, -1, 7, 8, -1 ]
highlightIndex -1
selectionIndex -1
}
}
PolygonOffset {
}
DEF myFaces Separator {
ShapeHints {
vertexOrdering UNKNOWN_ORDERING
shapeType UNKNOWN_SHAPE_TYPE
}
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0 0.66666669 1
specularColor 0 0 0
emissiveColor 0 0 0
shininess 0.2
transparency 0.5
}
DrawStyle {
style FILLED
}
Normal {
vector [ 0 0 1,
0 0 1,
0 0 1,
0 0 1,
0 0 1,
0 0 1,
0 -1 2.220446e-016,
0 -1 2.220446e-016,
0 -1 2.220446e-016 ]
}
NormalBinding {
value PER_VERTEX_INDEXED
}
SoBrepFaceSet {
fields [ SFNode vertexProperty, MFInt32 coordIndex, MFInt32 materialIndex, MFInt32 normalIndex, MFInt32 textureCoordIndex, MFInt32 partIndex, SFInt32 highlightIndex, MFInt32 selectionIndex ]
coordIndex [ 1, 0, 2, -1, 5, 4, 3, -1,
7, 6, 8, -1 ]
partIndex [ 1, 1, 1 ]
highlightIndex -1
selectionIndex -1
}
}
DEF myPoints Separator {
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0.25490198 0.67450982 0.89803922
specularColor 0 0 0
emissiveColor 0 0 0
shininess 1
transparency 0
}
DrawStyle {
style POINTS
pointSize 2
}
SoBrepPointSet {
fields [ SFNode vertexProperty, SFInt32 startIndex, SFInt32 numPoints, SFInt32 highlightIndex, MFInt32 selectionIndex ]
startIndex 9
highlightIndex -1
selectionIndex [ 9, 10, 11, 12, 13 ]
}
}
}
USE myFaces
Separator {
USE myLines
USE myPoints
}
USE myPoints
}

Binary file not shown.

View File

@ -0,0 +1,160 @@
#Inventor V2.1 ascii
PickStyle {
style UNPICKABLE
}
Coordinate3 {
point [ 0 0 0,
-1.7347235e-018 -0.30000001 1.3877788e-017,
1.7347235e-018 0.30000001 -2.1359844e-015,
-1.7347235e-018 8.3193401e-018 0.30000001,
1.7347235e-018 0.30000001 -2.1359844e-015,
0 0 0,
1 -2.7755576e-017 -2.0816682e-017,
-1.7347235e-018 -0.30000001 1.3877788e-017,
-1.7347235e-018 -0.30000001 1.3877788e-017,
1 -2.7755576e-017 -2.0816682e-017,
-1.7347235e-018 8.3193401e-018 0.30000001,
1 -2.7755576e-017 -2.0816682e-017,
-1.7347235e-018 8.3193401e-018 0.30000001,
1.7347235e-018 0.30000001 -2.1359844e-015,
0 0 0,
-1.7347235e-018 -0.30000001 1.3877788e-017,
1.7347235e-018 0.30000001 -2.1359844e-015,
-1.7347235e-018 8.3193401e-018 0.30000001,
1 -2.7755576e-017 -2.0816682e-017 ]
}
Switch {
whichChild 0
Separator {
DEF myLines Separator {
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0.33333334 0.65490198 0.87058824
specularColor 0 0 0
emissiveColor 0 0 0
shininess 1
transparency 0
}
DrawStyle {
style LINES
lineWidth 2
linePattern 0xffff
}
SoBrepEdgeSet {
fields [ SFNode vertexProperty, MFInt32 coordIndex, MFInt32 materialIndex, MFInt32 normalIndex, MFInt32 textureCoordIndex, SFInt32 highlightIndex, MFInt32 selectionIndex ]
coordIndex [ 0, 1, -1, 2, 0, -1, 1, 3,
-1, 3, 2, -1, 4, 6, -1, 7,
6, -1, 9, 10, -1 ]
highlightIndex 6
selectionIndex -1
}
}
PolygonOffset {
}
DEF myFaces Separator {
ShapeHints {
vertexOrdering UNKNOWN_ORDERING
shapeType UNKNOWN_SHAPE_TYPE
}
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0 0.66666669 1
specularColor 0 0 0
emissiveColor 0 0 0
shininess 0.2
transparency 0.5
}
DrawStyle {
style FILLED
}
Normal {
vector [ -1 0 0,
-1 0 0,
-1 0 0,
-1 0 0,
0 0 -1,
0 0 -1,
0 0 -1,
0 0 -1,
0.20751435 -0.69171447 0.69171447,
0.20751435 -0.69171447 0.69171447,
0.20751435 -0.69171447 0.69171447,
0.20751435 0.69171447 0.69171447,
0.20751435 0.69171447 0.69171447,
0.20751435 0.69171447 0.69171447 ]
}
NormalBinding {
value PER_VERTEX_INDEXED
}
SoBrepFaceSet {
fields [ SFNode vertexProperty, MFInt32 coordIndex, MFInt32 materialIndex, MFInt32 normalIndex, MFInt32 textureCoordIndex, MFInt32 partIndex, SFInt32 highlightIndex, MFInt32 selectionIndex ]
coordIndex [ 1, 3, 0, -1, 0, 3, 2, -1,
4, 6, 5, -1, 5, 6, 7, -1,
10, 8, 9, -1, 13, 12, 11, -1 ]
partIndex [ 2, 2, 1, 1 ]
highlightIndex -1
selectionIndex -1
}
}
DEF myPoints Separator {
MaterialBinding {
value OVERALL
}
Material {
ambientColor 0.2 0.2 0.2
diffuseColor 0.25490198 0.67450982 0.89803922
specularColor 0 0 0
emissiveColor 0 0 0
shininess 1
transparency 0
}
DrawStyle {
style POINTS
pointSize 2
}
SoBrepPointSet {
fields [ SFNode vertexProperty, SFInt32 startIndex, SFInt32 numPoints, SFInt32 highlightIndex, MFInt32 selectionIndex ]
startIndex 14
highlightIndex -1
selectionIndex [ 14, 15, 16, 17, 18 ]
}
}
}
USE myFaces
Separator {
USE myLines
USE myPoints
}
USE myPoints
}