Compare commits
41 Commits
master
...
reference-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
50f4372b02 | ||
![]() |
af75a3a0f0 | ||
![]() |
f874b338e7 | ||
![]() |
e18a270636 | ||
![]() |
dfa4377013 | ||
![]() |
0224b6f98a | ||
![]() |
f7bbd41b2c | ||
![]() |
e4c342f5ba | ||
![]() |
b8d3df590c | ||
![]() |
56c39bd493 | ||
![]() |
870ef63088 | ||
![]() |
a192e19209 | ||
![]() |
7d2d62bdea | ||
![]() |
32e840a941 | ||
![]() |
d8a3293dbc | ||
![]() |
64879965ba | ||
![]() |
3a2662685e | ||
![]() |
22925c8187 | ||
![]() |
c3bb345c3f | ||
![]() |
7331c60ce5 | ||
![]() |
340c51b108 | ||
![]() |
c566979574 | ||
![]() |
a80c075b4a | ||
![]() |
8cb8ab7bd9 | ||
![]() |
1e4416dd9f | ||
![]() |
fb031132e3 | ||
![]() |
5a72dedd4c | ||
![]() |
8f15765047 | ||
![]() |
65c6dad39f | ||
![]() |
9d2043f546 | ||
![]() |
7d0d5d63a3 | ||
![]() |
618bbc331f | ||
![]() |
bd3ac15fd2 | ||
![]() |
681c7330ba | ||
![]() |
c97e733c6a | ||
![]() |
eecd808a22 | ||
![]() |
62c6b6d7cc | ||
![]() |
f4b88d1a2e | ||
![]() |
6c620b130f | ||
![]() |
9449dd9352 | ||
![]() |
c7dd44868e |
|
@ -63,7 +63,7 @@ class Lattice2Workbench (Workbench):
|
|||
+ Lattice2.ArrayFeatures.JoinArrays.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.ArrayFilter.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.ProjectArray.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.InterpolateGroup.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.Resample2.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.PopulateCopies.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.PopulateChildren.exportedCommands
|
||||
+ Lattice2.ArrayFeatures.Mirror.exportedCommands
|
||||
|
@ -94,7 +94,6 @@ class Lattice2Workbench (Workbench):
|
|||
cmdsGuiTools = ([]
|
||||
+ Lattice2.GuiTools.Inspect.exportedCommands
|
||||
+ Lattice2.GuiTools.SubstituteObject.exportedCommands
|
||||
+ Lattice2.GuiTools.ViewFromPlacement.exportedCommands
|
||||
)
|
||||
self.appendToolbar('Lattice2GuiTools', cmdsGuiTools)
|
||||
self.appendMenu('Lattice2', cmdsGuiTools + Lattice2.GuiTools.ExposeLinkSub.exportedCommands)
|
||||
|
|
|
@ -2,7 +2,6 @@ import lattice2ArrayFilter as ArrayFilter
|
|||
import lattice2ArrayFromShape as ArrayFromShape
|
||||
import lattice2AttachablePlacement as AttachablePlacement
|
||||
import lattice2BaseFeature as BaseFeature
|
||||
import lattice2InterpolateGroup as InterpolateGroup
|
||||
import lattice2Invert as Invert
|
||||
import lattice2JoinArrays as JoinArrays
|
||||
import lattice2LinearArray as LinearArray
|
||||
|
@ -13,5 +12,5 @@ import lattice2PopulateChildren as PopulateChildren
|
|||
import lattice2PopulateCopies as PopulateCopies
|
||||
import lattice2ProjectArray as ProjectArray
|
||||
import lattice2Resample as Resample
|
||||
import lattice2ScLERP as ScLERP
|
||||
import lattice2Resample2 as Resample2
|
||||
import lattice2Mirror as Mirror
|
|
@ -8,4 +8,5 @@ import lattice2Markers as Markers
|
|||
import lattice2ValueSeriesGenerator as ValueSeriesGenerator
|
||||
import lattice2ShapeCopy as ShapeCopy
|
||||
import lattice2Subsequencer as Subsequencer
|
||||
import lattice2Utils as Utils
|
||||
import lattice2Utils as Utils
|
||||
import lattice2CoinGlue as CoinGlue
|
|
@ -1,5 +1,4 @@
|
|||
import lattice2Inspect as Inspect
|
||||
import lattice2RecomputeLocker as RecomputeLocker
|
||||
import lattice2SubstituteObject as SubstituteObject
|
||||
import lattice2ExposeLinkSub as ExposeLinkSub
|
||||
import lattice2ViewFromPlacement as ViewFromPlacement
|
||||
import lattice2Inspect as Inspect
|
||||
import lattice2RecomputeLocker as RecomputeLocker
|
||||
import lattice2SubstituteObject as SubstituteObject
|
||||
import lattice2ExposeLinkSub as ExposeLinkSub
|
|
@ -34,15 +34,19 @@
|
|||
<file>icons/Lattice2_PopulateChildren_Array.svg</file>
|
||||
<file>icons/Lattice2_PopulateChildren_Move.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_Normal.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_Move.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_Normal.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_RecomputeLocker_ForceRecompute.svg</file>
|
||||
<file>icons/Lattice2_RecomputeLocker_Locked.svg</file>
|
||||
|
@ -67,6 +71,5 @@
|
|||
<file>icons/Lattice2_SubLinkSubsequence_Vertex.svg</file>
|
||||
<file>icons/Lattice2_SubstituteObject.svg</file>
|
||||
<file>icons/Lattice2_TopoSeries.svg</file>
|
||||
<file>icons/Lattice2_ViewFromPlacement.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
448
PyResources/icons/Lattice2_PopulateChildren_Plms_Ref.svg
Normal file
448
PyResources/icons/Lattice2_PopulateChildren_Plms_Ref.svg
Normal 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 |
461
PyResources/icons/Lattice2_PopulateChildren_Ref.svg
Normal file
461
PyResources/icons/Lattice2_PopulateChildren_Ref.svg
Normal 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 |
440
PyResources/icons/Lattice2_PopulateCopies_Plms_Ref.svg
Normal file
440
PyResources/icons/Lattice2_PopulateCopies_Plms_Ref.svg
Normal 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 |
441
PyResources/icons/Lattice2_PopulateCopies_Ref.svg
Normal file
441
PyResources/icons/Lattice2_PopulateCopies_Ref.svg
Normal 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 |
|
@ -1,408 +0,0 @@
|
|||
<?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="svg2726"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Lattice2_ViewFromPlacement.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2728">
|
||||
<linearGradient
|
||||
id="linearGradient3916">
|
||||
<stop
|
||||
style="stop-color:#00ffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3918" />
|
||||
<stop
|
||||
id="stop3924"
|
||||
offset="0.61475408"
|
||||
style="stop-color:#00ffff;stop-opacity:0.9927361;" />
|
||||
<stop
|
||||
style="stop-color:#00ffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3920" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3908">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3910" />
|
||||
<stop
|
||||
style="stop-color:#74bdc6;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3912" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3766">
|
||||
<stop
|
||||
style="stop-color:#004bed;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3768" />
|
||||
<stop
|
||||
style="stop-color:#bbd7ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3770" />
|
||||
</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="perspective2734" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3144-4"
|
||||
id="radialGradient3850-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
cx="225.26402"
|
||||
cy="672.79736"
|
||||
fx="225.26402"
|
||||
fy="672.79736"
|
||||
r="34.345188" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3144-4">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3146-2" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3148-0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3766"
|
||||
id="linearGradient3772"
|
||||
x1="21.905107"
|
||||
y1="26.587624"
|
||||
x2="35.65699"
|
||||
y2="29.344099"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3908"
|
||||
id="radialGradient3914"
|
||||
cx="34.266594"
|
||||
cy="12.48589"
|
||||
fx="34.266594"
|
||||
fy="12.48589"
|
||||
r="28.220161"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3916"
|
||||
id="radialGradient3922"
|
||||
cx="46.773899"
|
||||
cy="24.764751"
|
||||
fx="46.773899"
|
||||
fy="24.764751"
|
||||
r="6.4209293"
|
||||
gradientTransform="matrix(1,0,0,1.1245231,0,-3.083783)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3908"
|
||||
id="radialGradient4080"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="34.266594"
|
||||
cy="12.48589"
|
||||
fx="34.266594"
|
||||
fy="12.48589"
|
||||
r="28.220161" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3916"
|
||||
id="radialGradient4082"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,1.1245231,0,-3.083783)"
|
||||
cx="46.773899"
|
||||
cy="24.764751"
|
||||
fx="46.773899"
|
||||
fy="24.764751"
|
||||
r="6.4209293" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8.7548828"
|
||||
inkscape:cx="35.247365"
|
||||
inkscape:cy="39.839989"
|
||||
inkscape:current-layer="g4289"
|
||||
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:snap-global="false"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-nodes="true" />
|
||||
<metadata
|
||||
id="metadata2731">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g4289"
|
||||
transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)">
|
||||
<g
|
||||
id="g3081"
|
||||
transform="matrix(0.7936378,0,0,0.7936378,-16.761355,242.67638)">
|
||||
<path
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3077"
|
||||
d="M 39.178137,29.84763 39.063915,47.666258 76.985611,41.612493 z"
|
||||
style="fill:#ffb380;stroke:#000000;stroke-width:1.26002061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3075"
|
||||
d="M 3.6551032,30.190296 38.949693,29.84763 53.79855,22.651645 76.871389,41.498271 z"
|
||||
style="fill:#ff6600;stroke:#000000;stroke-width:1.26002061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3079"
|
||||
d="M 39.178137,29.733408 76.528723,41.269827"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.26002061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4048"
|
||||
transform="matrix(0.75122203,0,0,0.75122203,7.0716755,157.31061)">
|
||||
<g
|
||||
id="g4044">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#radialGradient4080);fill-opacity:1;stroke:#000000;stroke-width:0.93181503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path3088"
|
||||
sodipodi:cx="41.462578"
|
||||
sodipodi:cy="22.537424"
|
||||
sodipodi:rx="27.870161"
|
||||
sodipodi:ry="27.870161"
|
||||
d="m 69.332739,22.537424 c 0,15.392265 -12.477896,27.870161 -27.870161,27.870161 -15.392265,0 -27.870161,-12.477896 -27.870161,-27.870161 0,-15.3922648 12.477896,-27.870161 27.870161,-27.870161 15.392265,0 27.870161,12.4778962 27.870161,27.870161 z"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-67.412564,417.6196)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#d0f0ff;stroke-width:1.3141346;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4011"
|
||||
sodipodi:cx="35.92281"
|
||||
sodipodi:cy="22.594534"
|
||||
sodipodi:rx="26.442387"
|
||||
sodipodi:ry="26.442387"
|
||||
d="m 62.365196,22.594534 c 0,14.603727 -11.83866,26.442387 -26.442386,26.442387 -14.603727,0 -26.442387,-11.83866 -26.442387,-26.442387 0,-14.603727 11.83866,-26.4423867 26.442387,-26.4423867 14.603726,0 26.442386,11.8386597 26.442386,26.4423867 z"
|
||||
transform="matrix(6.2478887,0,0,6.2478887,-36.4671,415.1091)" />
|
||||
</g>
|
||||
<g
|
||||
id="g4031">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.93181503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path3096"
|
||||
sodipodi:cx="47.859009"
|
||||
sodipodi:cy="24.993196"
|
||||
sodipodi:rx="9.2519798"
|
||||
sodipodi:ry="11.479308"
|
||||
d="m 57.110989,24.993196 c 0,6.339847 -4.142253,11.479309 -9.25198,11.479309 -5.109728,0 -9.25198,-5.139462 -9.25198,-11.479309 0,-6.339846 4.142252,-11.479308 9.25198,-11.479308 5.109727,0 9.25198,5.139462 9.25198,11.479308 z"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#radialGradient4082);fill-opacity:1;stroke:#000000;stroke-width:0.82546496;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path3102"
|
||||
sodipodi:cx="46.773899"
|
||||
sodipodi:cy="24.764751"
|
||||
sodipodi:rx="6.1108756"
|
||||
sodipodi:ry="6.9104295"
|
||||
d="m 52.884775,24.764751 c 0,3.816525 -2.735933,6.91043 -6.110876,6.91043 -3.374943,0 -6.110876,-3.093905 -6.110876,-6.91043 0,-3.816524 2.735933,-6.910429 6.110876,-6.910429 3.374943,0 6.110876,3.093905 6.110876,6.910429 z"
|
||||
transform="matrix(6.5138252,0,0,7.44233,-56.818481,375.84461)" />
|
||||
<path
|
||||
style="fill:#71c2cb;fill-opacity:1;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 47.84375,13.5 c -2.838498,0 -5.365342,1.597032 -7.0625,4.09375 L 54.8125,17.4375 C 53.116709,15.036713 50.618807,13.5 47.84375,13.5 z"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
id="path3104"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#71c2cb;fill-opacity:1;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 55.21875,31.9375 -14.625,0.15625 c 1.694454,2.659483 4.305537,4.375 7.25,4.375 3.00131,0 5.684617,-1.783204 7.375,-4.53125 z"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
id="path3106"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g4037">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.96294999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path3094"
|
||||
sodipodi:cx="46.259899"
|
||||
sodipodi:cy="23.679644"
|
||||
sodipodi:rx="15.648411"
|
||||
sodipodi:ry="19.303514"
|
||||
d="m 61.90831,23.679644 c 0,10.661036 -7.006032,19.303514 -15.648411,19.303514 -8.642379,0 -15.648411,-8.642478 -15.648411,-19.303514 0,-10.661037 7.006032,-19.3035148 15.648411,-19.3035148 8.642379,0 15.648411,8.6424778 15.648411,19.3035148 z"
|
||||
transform="matrix(6.100426,0,0,5.8394873,-43.505289,423.28413)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 33.58126,-3.5051867 c 3.54906,0.4949619 7.681075,5.9014686 8.338205,9.0235359"
|
||||
id="path3132"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 43.290128,-2.477189 c 3.173241,0.5667431 6.242341,5.2801913 7.767094,8.909314"
|
||||
id="path3134"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 34.609258,50.636029 c 3.587197,-0.06637 6.111433,-4.335444 6.739097,-6.510653"
|
||||
id="path3136"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 42.947462,49.379587 c 2.854355,-0.247839 5.896329,-2.986542 6.739097,-5.711098"
|
||||
id="path3138"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4021">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5.32465744;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 59.052761,6.2036811 7.767094,-9.137758"
|
||||
id="path3985"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5.32465744;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 27.641718,3.2339098 22.044841,4.0334636 28.098606,-7.5029558"
|
||||
id="path3983"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 27.527496,-8.5309536 26.04261,-7.2745119 20.902621,3.0054658"
|
||||
id="path3993"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 66.705633,-4.4189625 -1.370664,0.4568879"
|
||||
id="path3995"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 63.05053,-0.99230329 57.910541,4.8330173"
|
||||
id="path3997"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:3.99349308;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 27.984384,-6.817624 c 11.913444,0.2990197 23.422626,-0.00835 38.264361,4.683101"
|
||||
id="path3999"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 30.497267,-7.8456217 c 9.550041,0.1098683 18.431209,-0.2261788 34.15237,3.9977691"
|
||||
id="path4001"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 25.928388,1.7490241 28.32705,1.4063582"
|
||||
id="path4003"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
</g>
|
||||
<g
|
||||
id="g4013">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5.32465744;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 59.395427,41.498271 6.624874,9.480424"
|
||||
id="path3989"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5.32465744;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 28.669716,45.49604 24.32928,45.267596 28.555494,57.375125"
|
||||
id="path3987"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:3.99349308;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 28.212828,56.004462 c 12.894467,0.0155 25.507911,-0.980681 36.893697,-6.396431"
|
||||
id="path3991"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 29.240825,43.668489 -4.797323,0.342666 0.571111,1.370663 3.540881,11.307976"
|
||||
id="path4005"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 30.611489,55.090686 C 40.66419,54.628427 50.339639,54.783489 63.62164,49.036921"
|
||||
id="path4007"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.33116436px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 59.509649,41.041383 6.510652,9.25198"
|
||||
id="path4009"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 19 KiB |
112
README.md
112
README.md
|
@ -1,112 +0,0 @@
|
|||
# Lattice2 Workbench
|
||||
[](https://lgtm.com/projects/g/DeepSOIC/Lattice2/alerts/) [](https://lgtm.com/projects/g/DeepSOIC/Lattice2/context:python)
|
||||
|
||||
Lattice Workbench is a plug-in module/addon (workbench) for FreeCAD.
|
||||
|
||||
It's purpose is working with placements and arrays of placements. It functions similar to what an Assembly workbench does, but with emphasis on arrays. There are **no** constraints and relations, there are just arrays of placements that can be generated, combined, transformed, superimposed, and populated with shapes.
|
||||
|
||||
Ever wondered how to create a protractor with FreeCAD? That's the aim of this workbench (including tick labeling). Also, exploded assemblies can be made with this workbench.
|
||||
|
||||
Additionally, the workbench features a few general-purpose tools, such as parametric downgrade, bounding boxes, shape info tool, and tools for working with collections of shapes (compounds).
|
||||
|
||||
One of the big design goals of the workbench is being as parametric as possible.
|
||||
|
||||
## Getting started
|
||||
|
||||
Follow through the [Basic Tutorial](https://github.com/DeepSOIC/Lattice2/wiki/Basic-Tutorial) to get the basic concept of Lattice2.
|
||||
|
||||
## Highlights
|
||||

|
||||
|
||||

|
||||
|
||||
Take a look at other examples in the [Gallery of screenshots](https://github.com/DeepSOIC/Lattice2/wiki/Gallery).
|
||||
|
||||
## Features
|
||||
Let's have a glance over the most important capabilities that the workbench adds to FreeCAD:
|
||||
|
||||
* Re-use arrays as many times as you need. Unlike Draft array, which directly generates the array of shapes, lattice array tools generate arrays of placements. These can later be populated with shapes, as many times as necessary, without having to set up another array.
|
||||
* Extends PartDesign workflow, offering a way to reuse a sequence of features in arbitrary bodies and places.
|
||||
* Elements of array can be different. Unlike Draft Arrays, which always generate a set of equal shapes, Lattice arrays can be used to arrange a set of different shapes. Pack the shapes to be arranged into a Compound, and use Lattice [Populate with children](https://github.com/DeepSOIC/Lattice2/wiki/Feature-PopulateChildren) feature to arrange them.
|
||||
* Arrays of placements can be combined, inverted, generated from existing shape arrangements, made from individual placements, projected onto shapes, filtered, etc. This allows to produce complex arrangements without scripting.
|
||||
* Single placements can be used for primitive assembling of parts.
|
||||
* linear arrays and polar arrays can have their axes linked to edges of shapes
|
||||
* [ParaSeries](https://github.com/DeepSOIC/Lattice2/wiki/Feature-ParaSeries) feature allows to generate a series of parts with some parameter varied over a list of values.
|
||||
|
||||
## Why Lattice2, not just Lattice?
|
||||
Lattice2 was created at the moment when breaking changes needed to be made to Lattice, but there were a few things made with Lattice. So, it was decided to keep the workbench in that time's state indefinitely as version 1.0, and start development of a new version.
|
||||
|
||||
The goal was to allow editing old projects made with Lattice v1, by having both versions installed at the same time. So a new repository was started, and all the files were renamed to start with 'lattice2' or otherwise differ from those of Lattice v1.
|
||||
|
||||
Lattice3 (if ever) will be a standalone repository, for the same reasons.
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* FreeCAD >= `v0.16.5155`
|
||||
* PartDesign tools require `v0.17+`
|
||||
* Both Py2/Qt4 and Py3/Qt5 builds are supported.
|
||||
|
||||
The workbench is OS independent, it should work on any system FreeCAD can be run on. If you find that it doesn't - that is a bug. Please open an ticket in the [issue queue](https://github.com/DeepSOIC/Lattice2/issues).
|
||||
|
||||
**Note:** Lattice2 is written in FreeCAD's Python, and **must be run from within FreeCAD**. It requires no compilation, and can be installed by copying the repository to a special location.
|
||||
|
||||
### Automated install
|
||||
|
||||
There are several options to automate installation of this workbench.
|
||||
* The **most recommended method** is to use FreeCAD's built-in [Addon Manager](https://github.com/FreeCAD/FreeCAD-addons#1-builtin-addon-manager) (Tools > Addon manager).
|
||||
* Another method; Lattice2 workbench is packaged to Launchpad in the Ubuntu FreeCAD Community PPA (thanks to @abdullahtahiriyo).
|
||||
* Lattice2 can be installed via @microelly's [Plugin Loader](https://github.com/microelly2/freecad-pluginloader) (this option is deprecated).
|
||||
|
||||
**Note:** Any of the above options will require a restart of FreeCAD in order for the workbench to function.
|
||||
|
||||
### Manual install
|
||||
|
||||
<details>
|
||||
<summary>Expand this section if you prefer to manually install Lattice2</summary>
|
||||
|
||||
1. Download the workbench. There are several ways to do this, you can choose either:
|
||||
* Scroll to the top of the page, and click 'clone or download' -> 'download zip' button
|
||||
* `git clone https://github.com/DeepSOIC/Lattice2`
|
||||
2. If you downloaded the .zip, unpack the archive and rename it to `Lattice2`. If you used `git clone` then ignore this step.
|
||||
3. Move the newly created `Lattice2` directory to where your default FreeCAD install directory is located:
|
||||
* Windows: (sytem-wide install) `%AppData%\FreeCAD\Mod\Lattice2`
|
||||
* Windows: (for individual installs)
|
||||
`C:\Program Files\FreeCAD\Mod\Lattice2`
|
||||
* Linux: `~/.FreeCAD/Mod/Lattice2`
|
||||
* MacOS: `~/.FreeCAD/Mod/Lattice2`
|
||||
3. Restart FreeCAD
|
||||
|
||||
**Important Note:** Make sure that `InitGui.py` (and the rest of `.py` files) end up directly under `Mod\Lattice2` directory (**not** under nested directory like `Mod\Lattice2\Lattice2`).
|
||||
|
||||
</details>
|
||||
|
||||
## Usage
|
||||
|
||||
After installing the workbench and restarting FC, Lattice2 should now appear in the workbench dropdown menu. It will be listed down towards the bottom of list. Now, you can familiarize yourself with Lattice2 through the [Basic Tutorial](https://github.com/DeepSOIC/Lattice2/wiki/Basic-Tutorial).
|
||||
|
||||
Side Note: If you want to install the workbench for development, `git clone` the repository wherever you like, and make a symlink in where FreeCAD can pick it up as an add-on.
|
||||
|
||||
## Status
|
||||
|
||||
The workbench is stable. I will take care to not make breaking changes, and some new functionality may keep coming.
|
||||
|
||||
If you make your FreeCAD project using Lattice2, all further changes to the project must be done with Lattice2 installed, even if you don't touch the relevant features. Otherwise, the parametric features in the project will lose their bound functionality, and will not recompute, even if you install Lattice2 later. This is the case for all add-ons in FreeCAD, not just Lattice2.
|
||||
|
||||
## Getting Help
|
||||
|
||||
For Documentation see the [Lattice2 wiki](https://github.com/DeepSOIC/Lattice2/wiki) on Github. As the word "wiki" suggests, you can help by editing the documentation.
|
||||
|
||||
If you need help on something specific, you can ask a question on [FreeCAD forum](http://forum.freecadweb.org/) (there is no Lattice forum yet...). You can also ask me directly. **Note:** If you post to the forum, please add this to your post so that I get a notification:
|
||||
`[quote=DeepSOIC user_id=3888]Ding![/quote]`
|
||||
|
||||
## Contributing
|
||||
|
||||
If you have found a bug or are requesting a new feature, please first check to see if it has been previously reported already on the [Lattice2 Github repo issue tracker](https://github.com/DeepSOIC/Lattice2/issues). If not, feel free to open a ticket.
|
||||
|
||||
If you have fixed a bug or implemented a new feature you think suits the workbench, feel free to make a pull-request on Github.
|
||||
|
||||
## License
|
||||
|
||||
Lattice workbench is licensed under LGPL V2, just like FreeCAD. For more info, see [copying.lib](copying.lib) file in this repository.
|
|
@ -60,9 +60,9 @@ class LatticeArrayFilter(lattice2BaseFeature.LatticeFeature):
|
|||
|
||||
obj.addProperty("App::PropertyLink","Stencil","Lattice ArrayFilter","Object that defines filtering")
|
||||
|
||||
obj.addProperty("App::PropertyLength","WindowFrom","Lattice ArrayFilter","Elements closer to stencil than this value are rejected by the filter.")
|
||||
obj.addProperty("App::PropertyLength","WindowFrom","Lattice ArrayFilter","Elements closer to stencil than this vaule are rejected by the filter.")
|
||||
obj.WindowFrom = 0.0
|
||||
obj.addProperty("App::PropertyLength","WindowTo","Lattice ArrayFilter","Elements farther from stencil than this value are rejected by the filter.")
|
||||
obj.addProperty("App::PropertyLength","WindowTo","Lattice ArrayFilter","Elements farther from stencil than this vaule are rejected by the filter.")
|
||||
obj.WindowTo = 1.0
|
||||
|
||||
obj.addProperty("App::PropertyBool","Invert","Lattice ArrayFilter","Output elements that are rejected by filter, instead")
|
||||
|
@ -70,6 +70,20 @@ class LatticeArrayFilter(lattice2BaseFeature.LatticeFeature):
|
|||
|
||||
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):
|
||||
#validity check
|
||||
|
@ -128,7 +142,9 @@ class LatticeArrayFilter(lattice2BaseFeature.LatticeFeature):
|
|||
output.append(input[i])
|
||||
else:
|
||||
raise ValueError('Filter mode not implemented:'+obj.FilterType)
|
||||
|
||||
|
||||
self.setReferencePlm(obj, lattice2BaseFeature.getReferencePlm(obj.Base))
|
||||
|
||||
return output
|
||||
|
||||
|
||||
|
@ -188,11 +204,11 @@ def makeItemListFromSelection(sel, bMakeString = True):
|
|||
def CreateLatticeArrayFilter(name,mode):
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
|
||||
# selection order independence logic (lattice object and generic shape stencil can be told apart)
|
||||
# selection order independece logic (lattice object and generic shape stencil can be told apart)
|
||||
iLtc = 0 #index of lattice object in selection
|
||||
iStc = 1 #index of stencil object in selection
|
||||
for i in range(0,len(sel)):
|
||||
if lattice2BaseFeature.isObjectLattice(sel[i]):
|
||||
if lattice2BaseFeature.isObjectLattice(sel[i].Object):
|
||||
iLtc = i
|
||||
iStc = i-1 #this may give negative index, but python accepts negative indexes
|
||||
break
|
||||
|
@ -301,7 +317,7 @@ class GroupCommandLatticeArrayFilter:
|
|||
|
||||
def GetResources(self):
|
||||
return { 'MenuText': 'Array filter:',
|
||||
'ToolTip': 'Array filter: tool to extract specific elements from lattice2 arrays.'}
|
||||
'ToolTip': 'Array filter: tool to exctract specific elements from lattice2 arrays.'}
|
||||
|
||||
def IsActive(self): # optional
|
||||
return bool(App.ActiveDocument)
|
||||
|
|
|
@ -40,7 +40,7 @@ EDIT_ATTACHMENT = 56 # Viewprovider edit mode number
|
|||
def makeAttachablePlacement(name):
|
||||
'''makeAttachablePlacement(name): makes an attachable Placement object.'''
|
||||
if Compat.attach_extension_era:
|
||||
obj = lattice2BaseFeature.makeLatticeFeature(name, AttachablePlacement, ViewProviderAttachablePlacement, no_disable_attacher= True)
|
||||
obj = lattice2BaseFeature.makeLatticeFeature(name, AttachablePlacement, ViewProviderAttachablePlacement)
|
||||
else:
|
||||
#obsolete!
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::AttachableObjectPython",name)
|
||||
|
@ -53,15 +53,12 @@ def makeAttachablePlacement(name):
|
|||
class AttachableFeature(lattice2BaseFeature.LatticeFeature):
|
||||
"Base class for attachable features"
|
||||
|
||||
attachable = True
|
||||
|
||||
def derivedInit(self,obj):
|
||||
if Compat.attach_extension_era:
|
||||
if not obj.hasExtension('Part::AttachExtension'): #PartDesign-related hack: the placement already has attachextension if created in PD
|
||||
obj.addExtension('Part::AttachExtensionPython', None)
|
||||
|
||||
def onDocumentRestored(self, selfobj):
|
||||
#PartDesign-related hack: this dummy override disables disabling of attacher
|
||||
pass
|
||||
|
||||
|
||||
class AttachablePlacement(AttachableFeature):
|
||||
"Attachable Lattice Placement object"
|
||||
|
@ -79,9 +76,8 @@ class AttachablePlacement(AttachableFeature):
|
|||
|
||||
class ViewProviderAttachableFeature(lattice2BaseFeature.ViewProviderLatticeFeature):
|
||||
always_edit_attachment = False
|
||||
|
||||
def setEdit(self,vobj,mode):
|
||||
if not (mode == EDIT_ATTACHMENT or (mode == 0 and self.always_edit_attachment)): raise NotImplementedError()
|
||||
if not (mode == EDIT_ATTACHMENT or (mode == 0 and always_edit_attachment)): raise NotImplementedError()
|
||||
import PartGui
|
||||
import FreeCADGui as Gui
|
||||
PartGui.AttachmentEditor.editAttachment(self.Object,
|
||||
|
@ -90,7 +86,7 @@ class ViewProviderAttachableFeature(lattice2BaseFeature.ViewProviderLatticeFeatu
|
|||
return True
|
||||
|
||||
def unsetEdit(self,vobj,mode):
|
||||
if not (mode == EDIT_ATTACHMENT or (mode == 0 and self.always_edit_attachment)): raise NotImplementedError()
|
||||
if not (mode == EDIT_ATTACHMENT or (mode == 0 and always_edit_attachment)): raise NotImplementedError()
|
||||
import FreeCADGui as Gui
|
||||
Gui.Control.closeDialog()
|
||||
return True
|
||||
|
@ -123,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::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']
|
||||
|
||||
|
||||
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):
|
||||
attacher = Part.AttachEngine(screen(obj.Base).AttacherType)
|
||||
attacher.readParametersFromFeature(screen(obj.Base))
|
||||
|
@ -134,10 +147,31 @@ class AttachedPlacementSubsequence(lattice2BaseFeature.LatticeFeature):
|
|||
sublinks = Subsequencer.Subsequence_auto(attacher.References,
|
||||
loop= ('Till end' if obj.CycleMode == 'Open' else 'All around'),
|
||||
index_filter= ifilt)
|
||||
|
||||
deref = obj.Base.Placement.inverse()
|
||||
basearray = [deref.multiply(plm) for plm in lattice2BaseFeature.getPlacementsList(obj.Base)]
|
||||
|
||||
plms = []
|
||||
for lnkval in sublinks:
|
||||
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
|
||||
|
||||
class ViewProviderAttachedPlacementSubsequence(lattice2BaseFeature.ViewProviderLatticeFeature):
|
||||
|
@ -168,11 +202,8 @@ def CreateAttachablePlacement(name):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create Attachable Placement")
|
||||
FreeCADGui.addModule("lattice2AttachablePlacement")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.addModule("PartGui")
|
||||
FreeCADGui.doCommand("f = lattice2AttachablePlacement.makeAttachablePlacement(name='"+name+"')")
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.MarkerSize = lattice2Base.Autosize.convenientMarkerSize()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCADGui.doCommand("lattice2AttachablePlacement.editNewAttachment(f)")
|
||||
#FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
@ -235,7 +266,7 @@ class CommandAttachedPlacementSubsequence:
|
|||
"\n\nPlease select an attached placement object, first. Then invoke this tool. Adjust the properties of the created object if necessary." )
|
||||
else:
|
||||
if len(sel)!=1:
|
||||
raise SelectionError("PlacementSubsequence", "Please select just one object, an attached placement. You have selected {num}.".format(num= len(sel)))
|
||||
raise SelectionError("PlacementSubsequence", "Please select just one object, an attached placement. You have seleced {num}.".format(num= len(sel)))
|
||||
cmdCreateAttachedPlacementSubsequence(name= "PlacementSubsequence")
|
||||
except Exception as err:
|
||||
msgError(err)
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* 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__= "Lattice2 Autosize module"
|
||||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
__doc__ = (
|
||||
"""helper module for Lattice add-on workbench for FreeCAD. Routines used to guess sizes for primitives.
|
||||
"""
|
||||
)
|
||||
|
||||
from . import Rounder
|
||||
from . import Containers
|
||||
|
||||
import FreeCAD as App
|
||||
import math
|
||||
from math import radians
|
||||
|
||||
|
||||
def convenientModelWidth():
|
||||
"""convenientModelWidth(): returns a size that will conveniently fit in the width of screen"""
|
||||
return Autosize().convenientModelWidth()
|
||||
def convenientModelSize():
|
||||
"""convenientModelSize(): returns a size of a box that will conveniently fit in the screen"""
|
||||
return Autosize().convenientModelSize()
|
||||
def minimalSize():
|
||||
"""minimalSize(): returns a size that will be barely recognizable on the screen (it is a rounded pick radius in model space)"""
|
||||
return Autosize().minimalSize()
|
||||
def convenientMarkerSize():
|
||||
"""convenientMarkerSize(): size of object to be able to comfortably select faces"""
|
||||
return Autosize().convenientMarkerSize()
|
||||
def convenientFeatureSize():
|
||||
"""convenientFeatureSize(): size in between marker size and model size. Should be reasonable to edit, but not fill the whole screen."""
|
||||
return Autosize().convenientFeatureSize()
|
||||
def convenientPosition():
|
||||
return Autosize().convenientPosition()
|
||||
|
||||
def getLocalOriginPosition():
|
||||
ac = Containers.activeContainer()
|
||||
if ac is None:
|
||||
return App.Vector()
|
||||
elif ac.isDerivedFrom('App::Document'): #special case for v0.16
|
||||
return App.Vector()
|
||||
else:
|
||||
return Containers.Container(ac).getFullTransform().Base
|
||||
|
||||
def _printTraceback(err):
|
||||
import traceback
|
||||
tb = traceback.format_exc()
|
||||
App.Console.PrintError("Lattice Autosize error: {err}\n{tb}\n\n".format(err= str(err), tb= tb))
|
||||
|
||||
|
||||
class ViewportInfo(object):
|
||||
camera_type = 'perspective' #string: perspective or orthographic
|
||||
camera_placement = App.Placement(App.Vector(0,0,1), App.Rotation())
|
||||
camera_focalplacement = App.Placement()
|
||||
camera_focaldist = 1.0
|
||||
camera_heightangle = radians(45) #total horizontal view angle, in radians (for perspective camera)
|
||||
camera_height = 1 #screen height in model space (mm), for orthographic camera
|
||||
viewport_size_px = (1800,1000) #width, height of viewport, in pixels
|
||||
viewport_size_mm = (1.8,1.0) #width, height of viewport (on focal plane), in mm
|
||||
mm_per_px = 1.0 / 1000.0 #rough mm-to-pixel ratio (accurate on focal plane)
|
||||
false_viewport = False # if true, no actual viewport was queried (e.g. non-gui mode, or activeview is non-3d)
|
||||
|
||||
pickradius_px = 5
|
||||
pickradius_mm = 0.1
|
||||
|
||||
def __init__(self, viewer = None):
|
||||
try:
|
||||
if not(App.GuiUp or viewer is not None):
|
||||
return
|
||||
|
||||
if viewer == None:
|
||||
import FreeCADGui as Gui
|
||||
viewer = Gui.ActiveDocument.ActiveView
|
||||
|
||||
if not hasattr(viewer, 'getCameraNode'):
|
||||
return
|
||||
|
||||
import pivy
|
||||
cam = viewer.getCameraNode()
|
||||
self.camera_type = 'perspective' if isinstance(cam, pivy.coin.SoPerspectiveCamera) else 'orthographic'
|
||||
self.camera_placement = App.Placement(
|
||||
App.Vector(cam.position.getValue().getValue()),
|
||||
App.Rotation(*cam.orientation.getValue().getValue())
|
||||
)
|
||||
self.camera_focaldist = cam.focalDistance.getValue()
|
||||
self.camera_focalplacement = self.camera_placement.multiply(App.Placement(App.Vector(0,0,-self.camera_focaldist), App.Rotation()))
|
||||
|
||||
if self.camera_type == 'perspective':
|
||||
self.camera_heightangle = cam.heightAngle.getValue()
|
||||
self.camera_height = math.tan(self.camera_heightangle / 2) * self.camera_focaldist * 2
|
||||
else:
|
||||
self.camera_height = cam.height.getValue()
|
||||
self.camera_focaldist = self.camera_height / 2 / math.tan(radians(45)/2) #in parallel projection, focal distance has strange values. Reconstructing a focal distance for a typical perspective camera...
|
||||
|
||||
self.false_viewport = False
|
||||
|
||||
rman = viewer.getViewer().getSoRenderManager()
|
||||
self.viewport_size_px = tuple(rman.getWindowSize())
|
||||
|
||||
mmppx = self.camera_height/self.viewport_size_px[1]
|
||||
self.mm_per_px = mmppx
|
||||
|
||||
self.viewport_size_mm = (self.viewport_size_px[0]*mmppx, self.viewport_size_px[1]*mmppx)
|
||||
|
||||
self.pickradius_px = App.ParamGet("User parameter:BaseApp/Preferences/View").GetFloat("PickRadius", 5.0)
|
||||
self.pickradius_mm = self.pickradius_px * mmppx
|
||||
|
||||
except Exception as err:
|
||||
import traceback
|
||||
tb = traceback.format_exc()
|
||||
App.Console.PrintError("Lattice Autosize: failed to query viewport: {err}\n{tb}\n\n".format(err= str(err), tb= tb))
|
||||
|
||||
class Autosize(ViewportInfo):
|
||||
convenient_model_size_multiplier = 0.4
|
||||
def __init__(self, viewer = None):
|
||||
super(Autosize, self).__init__(viewer)
|
||||
|
||||
def convenientModelWidth(self):
|
||||
"""convenientModelWidth(): returns a size that will conveniently fit in the width of screen"""
|
||||
try:
|
||||
return Rounder.roundToNiceValue(self._convenientModelWidth())
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return 10.0
|
||||
|
||||
def convenientModelSize(self):
|
||||
"""convenientModelSize(): returns a size of a box that will conveniently fit in the screen"""
|
||||
try:
|
||||
return Rounder.roundToNiceValue(self._convenientModelSize())
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return 10.0
|
||||
|
||||
def minimalSize(self):
|
||||
"""minimalSize(): returns a size that will be barely recognizable on the screen (it is a rounded pick radius in model space)"""
|
||||
try:
|
||||
return Rounder.roundToNiceValue(self._minimalSize())
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return 0.1
|
||||
|
||||
def convenientMarkerSize(self):
|
||||
"""convenientMarkerSize(): size of object to be able to comfortably select faces"""
|
||||
try:
|
||||
return Rounder.roundToNiceValue(self._convenientMarkerSize())
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return 1.0
|
||||
|
||||
def convenientFeatureSize(self):
|
||||
"""convenientFeatureSize(): size in between marker size and model size. Should be reasonable to edit, but not fill the whole screen."""
|
||||
try:
|
||||
return Rounder.roundToNiceValue(self._convenientFeatureSize())
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return 5.0
|
||||
|
||||
def convenientPosition(self):
|
||||
try:
|
||||
if self.isPointInWorkingArea(getLocalOriginPosition()):
|
||||
return App.Vector()
|
||||
else:
|
||||
roundfocal = Rounder.roundToNiceValue(self.camera_focaldist*0.5)
|
||||
result = App.Vector(
|
||||
[Rounder.roundToPrecision(coord, roundfocal) for coord in tuple(self.camera_focalplacement.Base)]
|
||||
)
|
||||
return result
|
||||
except Exception as err:
|
||||
_printTraceback(err)
|
||||
return App.Vector()
|
||||
|
||||
def _convenientModelWidth(self):
|
||||
if self.false_viewport:
|
||||
return 10.0
|
||||
else:
|
||||
return self.viewport_size_mm[0] * self.convenient_model_size_multiplier
|
||||
def _convenientModelSize(self):
|
||||
"""_convenientMarkerSize(): (unrounded) returns size of an object that would fill most of the working area"""
|
||||
if self.false_viewport:
|
||||
return 10.0
|
||||
else:
|
||||
return min(self.viewport_size_mm[0], self.viewport_size_mm[1]) * self.convenient_model_size_multiplier
|
||||
|
||||
def _minimalSize(self):
|
||||
"""_minimalSize(): (unrounded) returns minimum object size that can be seen on screen on focal plane"""
|
||||
if self.false_viewport:
|
||||
return 0.1
|
||||
else:
|
||||
return self.pickradius_mm
|
||||
|
||||
def _convenientMarkerSize(self):
|
||||
"""_convenientMarkerSize(): (unrounded) returns maker size that is usefully large to select faces and understand its rotation"""
|
||||
if self is None:
|
||||
self = ViewportInfo()
|
||||
if self.false_viewport:
|
||||
return 1.0
|
||||
else:
|
||||
return self.pickradius_mm * 10
|
||||
|
||||
def _convenientFeatureSize(self):
|
||||
"""_convenientMarkerSize(): (unrounded) returns size of an object that would fill most of the working area"""
|
||||
if self is None:
|
||||
self = ViewportInfo()
|
||||
return math.sqrt(self._convenientModelSize() * self._convenientMarkerSize())
|
||||
|
||||
def isPointInWorkingArea(self, point = App.Vector()):
|
||||
"""isPointInWorkingArea(): returns True if point is not far from the visible area of focal plane. Point should be given in document coordinate system."""
|
||||
p_foc = self.camera_focalplacement.inverse().multVec(point)
|
||||
#p_foc is point in focal-plane CS. X and Y are along focal plane. Z is against view direction (positive = towards the camera).
|
||||
mheight = self.viewport_size_mm[1]*0.8
|
||||
mwidth = self.viewport_size_mm[0]*0.8
|
||||
f = self.camera_focaldist
|
||||
if abs(p_foc.x) > mwidth*0.5 or abs(p_foc.y) > mheight*0.5 or p_foc.z > f*0.5 or p_foc.z < -2*f:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
#/***************************************************************************
|
||||
# * Copyright (c) Victor Titov (DeepSOIC) *
|
||||
# * (vv.titov@gmail.com) 2018 *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
#This is a temporary replacement for C++-powered Container class that should be eventually introduced into FreeCAD
|
||||
|
||||
import FreeCAD as App
|
||||
|
||||
class Container(object):
|
||||
"""Container class: a unified interface for container objects, such as Group, Part, Body, or Document.
|
||||
This is a temporary implementation."""
|
||||
Object = None #DocumentObject or Document, the actual container
|
||||
|
||||
def __init__(self, obj):
|
||||
self.Object = obj
|
||||
|
||||
def self_check(self):
|
||||
if self.Object is None:
|
||||
raise ValueError("Null!")
|
||||
if not isAContainer(self.Object):
|
||||
raise NotAContainerError(self.Object)
|
||||
|
||||
def getAllChildren(self):
|
||||
"""Returns all objects directly contained by the container. all = static + dynamic."""
|
||||
return self.getStaticChildren() + self.getDynamicChildren()
|
||||
|
||||
def getStaticChildren(self):
|
||||
"""Returns children tightly bound to the container, such as Origin. The key thing
|
||||
about them is that they are not supposed to be removed or added from/to the container."""
|
||||
|
||||
self.self_check()
|
||||
container = self.Object
|
||||
if container.isDerivedFrom('App::Document'):
|
||||
return []
|
||||
elif container.hasExtension('App::OriginGroupExtension'):
|
||||
if container.Origin is not None:
|
||||
return [container.Origin]
|
||||
else:
|
||||
return []
|
||||
elif container.isDerivedFrom('App::Origin'):
|
||||
return container.OriginFeatures
|
||||
elif container.hasExtension('App::GroupExtension'):
|
||||
return []
|
||||
raise RuntimeError("getStaticChildren: unexpected container type!")
|
||||
|
||||
def getDynamicChildren(self):
|
||||
"""Returns dynamic children, i.e. the stuff that can be removed from the container."""
|
||||
self.self_check()
|
||||
container = self.Object
|
||||
|
||||
if container.isDerivedFrom('App::Document'):
|
||||
# find all objects not contained by any Part or Body
|
||||
result = set(container.Objects)
|
||||
for obj in container.Objects:
|
||||
if isAContainer(obj):
|
||||
children = set(Container(obj).getAllChildren())
|
||||
result = result - children
|
||||
return list(result)
|
||||
elif container.hasExtension('App::GroupExtension'):
|
||||
result = container.Group
|
||||
if container.hasExtension('App::GeoFeatureGroupExtension'):
|
||||
#geofeaturegroup's group contains all objects within the CS, we don't want that
|
||||
result = [obj for obj in result if obj.getParentGroup() is not container]
|
||||
return result
|
||||
elif container.isDerivedFrom('App::Origin'):
|
||||
return []
|
||||
raise RuntimeError("getDynamicChildren: unexpected container type!")
|
||||
|
||||
def isACS(self):
|
||||
"""isACS(): returns true if the container forms internal coordinate system."""
|
||||
self.self_check()
|
||||
container = self.Object
|
||||
|
||||
if container.isDerivedFrom('App::Document'):
|
||||
return True #Document is a special thing... is it a CS or not is a matter of coding convenience.
|
||||
elif container.hasExtension('App::GeoFeatureGroupExtension'):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def isAVisGroup(self):
|
||||
"""isAVisGroup(): returns True if the container consumes viewproviders of children, and thus affects their visibility."""
|
||||
self.self_check()
|
||||
container = self.Object
|
||||
|
||||
if container.isDerivedFrom('App::Document'):
|
||||
return True #Document is a special thing... Return value is a matter of coding convenience.
|
||||
elif container.hasExtension('App::GeoFeatureGroupExtension'):
|
||||
return True
|
||||
elif container.isDerivedFrom('App::Origin'):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def getCSChildren(self):
|
||||
if not self.isACS():
|
||||
raise TypeError("Container is not a coordinate system")
|
||||
container = self.Object
|
||||
return _getMetacontainerChildren(self, Container.isACS)
|
||||
|
||||
def getVisGroupChildren(self):
|
||||
if not self.isAVisGroup():
|
||||
raise TypeError("Container is not a visibility group")
|
||||
container = self.Object
|
||||
return _getMetacontainerChildren(self, Container.isAVisGroup)
|
||||
|
||||
def hasObject(self, obj):
|
||||
"""Returns True if the container contains specified object directly."""
|
||||
return obj in self.getAllChildren()
|
||||
|
||||
def hasObjectRecursive(self, obj):
|
||||
return self.Object in ContainerChain(obj)
|
||||
|
||||
def Placement(self):
|
||||
if self.isACS():
|
||||
if hasattr(self.Object, 'Placement'):
|
||||
return self.Object.Placement
|
||||
return App.Placement()
|
||||
|
||||
def getFullTransform(self):
|
||||
"""getFullTransform(): returns Placement that converts coordinates of objects in this container to global CS."""
|
||||
chain = ContainerChain(self.Object) + [self.Object]
|
||||
plm = App.Placement()
|
||||
for cnt in chain:
|
||||
plm = plm.multiply(Container(cnt).Placement())
|
||||
return plm
|
||||
|
||||
def _getMetacontainerChildren(container, isrightcontainer_func):
|
||||
"""Gathers up children of metacontainer - a container structure formed by containers of specific type.
|
||||
For example, coordinate systems form a kind of container structure.
|
||||
|
||||
container: instance of Container class
|
||||
isrightcontainer_func: a function f(cnt)->bool, where cnt is a Container object."""
|
||||
|
||||
result = []
|
||||
list_traversing_now = [container] #list of Container instances
|
||||
list_to_be_traversed_next = [] #list of Container instances
|
||||
visited_containers = set([container.Object]) #set of DocumentObjects
|
||||
|
||||
while len(list_traversing_now) > 0:
|
||||
list_to_be_traversed_next = []
|
||||
for itcnt in list_traversing_now:
|
||||
children = itcnt.getAllChildren()
|
||||
result.extend(children)
|
||||
for child in children:
|
||||
if isAContainer(child):
|
||||
newcnt = Container(child)
|
||||
if not isrightcontainer_func(newcnt):
|
||||
list_to_be_traversed_next.append(newcnt)
|
||||
list_traversing_now = list_to_be_traversed_next
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
def isAContainer(obj):
|
||||
'''isAContainer(obj): returns True if obj is an object container, such as
|
||||
Group, Part, Body. The important characteristic of an object being a
|
||||
container is that it can be activated to receive new objects. Documents
|
||||
are considered containers, too.'''
|
||||
|
||||
if obj.isDerivedFrom('App::Document'):
|
||||
return True
|
||||
if obj.hasExtension('App::GroupExtension'):
|
||||
return True
|
||||
if obj.isDerivedFrom('App::Origin'):
|
||||
return True
|
||||
return False
|
||||
|
||||
#from Part-o-magic...
|
||||
def ContainerOf(obj):
|
||||
"""ContainerOf(obj): returns the container that immediately has obj."""
|
||||
cnt = None
|
||||
for dep in obj.InList:
|
||||
if isAContainer(dep):
|
||||
if Container(dep).hasObject(obj):
|
||||
if cnt is not None and dep is not cnt:
|
||||
raise ContainerTreeError("Container tree is not a tree")
|
||||
cnt = dep
|
||||
if cnt is None:
|
||||
return obj.Document
|
||||
return cnt
|
||||
|
||||
def getVisGroupOf(obj):
|
||||
chain = VisGroupChain(obj)
|
||||
return chain[-1]
|
||||
|
||||
#from Part-o-magic... over-engineered, but proven to work
|
||||
def ContainerChain(feat):
|
||||
'''ContainerChain(feat): container path to feat (not including feat itself).
|
||||
Last container directly contains the feature.
|
||||
Example of output: [<document>,<SuperPart>,<Part>,<Body>]'''
|
||||
|
||||
if feat.isDerivedFrom('App::Document'):
|
||||
return []
|
||||
|
||||
list_traversing_now = [feat]
|
||||
set_of_deps = set()
|
||||
list_of_deps = []
|
||||
|
||||
while len(list_traversing_now) > 0:
|
||||
list_to_be_traversed_next = []
|
||||
for feat in list_traversing_now:
|
||||
for dep in feat.InList:
|
||||
if isAContainer(dep) and Container(dep).hasObject(feat):
|
||||
if not (dep in set_of_deps):
|
||||
set_of_deps.add(dep)
|
||||
list_of_deps.append(dep)
|
||||
list_to_be_traversed_next.append(dep)
|
||||
if len(list_to_be_traversed_next) > 1:
|
||||
raise ContainerTreeError("Container tree is not a tree")
|
||||
list_traversing_now = list_to_be_traversed_next
|
||||
|
||||
return [feat.Document] + list_of_deps[::-1]
|
||||
|
||||
def CSChain(feat):
|
||||
cnt_chain = ContainerChain(feat)
|
||||
return [cnt for cnt in cnt_chain if Container(cnt).isACS()]
|
||||
|
||||
def VisGroupChain(feat):
|
||||
cnt_chain = ContainerChain(feat)
|
||||
return [cnt for cnt in cnt_chain if Container(cnt).isAVisGroup()]
|
||||
|
||||
def activeContainer():
|
||||
'''activeContainer(): returns active container.
|
||||
If there is an active body, it is returned as active container. ActivePart is ignored.
|
||||
If there is no active body, active Part is returned.
|
||||
If there is no active Part either, active Document is returned.
|
||||
If no active document, None is returned.'''
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
|
||||
if hasattr(App, "ActiveContainer"):
|
||||
return App.ActiveContainer.Object
|
||||
|
||||
if Gui.ActiveDocument is None:
|
||||
return None
|
||||
vw = Gui.ActiveDocument.ActiveView
|
||||
if vw is None:
|
||||
return None
|
||||
if not hasattr(vw, 'getActiveObject'): #v0.16
|
||||
return App.ActiveDocument
|
||||
activeBody = vw.getActiveObject("pdbody")
|
||||
activePart = vw.getActiveObject("part")
|
||||
if activeBody:
|
||||
return activeBody
|
||||
elif activePart:
|
||||
return activePart
|
||||
else:
|
||||
return App.ActiveDocument
|
||||
|
||||
|
||||
class ContainerError(RuntimeError):
|
||||
pass
|
||||
class NotAContainerError(ContainerError):
|
||||
def __init__(self):
|
||||
ContainerError.__init__(self, u"{obj} is not recognized as container".format(obj.Name))
|
||||
class ContainerTreeError(ContainerError):
|
||||
pass
|
|
@ -1,106 +0,0 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* 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__= "Lattice2 rounder module"
|
||||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
__doc__ = "helper module for Lattice add-on workbench for FreeCAD. Provides special rounding routines."
|
||||
|
||||
import math
|
||||
from math import log
|
||||
|
||||
# copied from FreeCAD /src/Base/UnitsSchema.h, enum UnitSystem
|
||||
class UnitSystem(object):
|
||||
SI1 = 0 #, /** internal (mm,kg,s) SI system (http://en.wikipedia.org/wiki/International_System_of_Units) */
|
||||
SI2 = 1 #, /** MKS (m,kg,s) SI system */
|
||||
Imperial1 = 2 #, /** the Imperial system (http://en.wikipedia.org/wiki/Imperial_units) */
|
||||
ImperialDecimal = 3 #, /** Imperial with length in inch only */
|
||||
Centimeters = 4 #, /** All lengths in centimeters, areas and volumes in square/cubic meters */
|
||||
ImperialBuilding = 5 #, /** All lengths in feet + inches + fractions */
|
||||
MmMin = 6 #, /** Lengths in mm, Speed in mm/min. Angle in degrees. Useful for small parts & CNC */
|
||||
|
||||
@staticmethod
|
||||
def getActiveSchema():
|
||||
import FreeCAD as App
|
||||
return App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("UserSchema", 0)
|
||||
|
||||
def getNiceLengths(unitschema = None):
|
||||
if unitschema is None:
|
||||
unitschema = UnitSystem.getActiveSchema()
|
||||
if unitschema == UnitSystem.SI1 or unitschema == UnitSystem.SI2 or unitschema == UnitSystem.Centimeters or unitschema == UnitSystem.MmMin:
|
||||
nice_numbers = [1.0, 2.0, 5.0]
|
||||
nice_magnitudes = []
|
||||
for degree in range(-3,6):
|
||||
order = 10.0 ** degree
|
||||
nice_magnitudes.extend([order * val for val in nice_numbers])
|
||||
return nice_magnitudes
|
||||
elif unitschema == UnitSystem.Imperial1 or unitschema == UnitSystem.ImperialBuilding or unitschema == UnitSystem.ImperialDecimal:
|
||||
inch = 25.4
|
||||
foot = 304.8
|
||||
yard = 914.4
|
||||
mile = 1609344.0
|
||||
#https://forum.freecadweb.org/viewtopic.php?f=8&t=32565#p271923
|
||||
#.005" .010", .025", .050", .100", .250", 1", 6", 1', 8', 50', 100', 500', 1000', 2500', 1 mile, 10 miles, 100 miles
|
||||
return [
|
||||
0.005*inch,
|
||||
0.010*inch, 0.025*inch, 0.050*inch,
|
||||
0.10*inch, 0.25*inch, 0.50*inch,
|
||||
1*inch, 2*inch, 6*inch,
|
||||
|
||||
1*foot, 2*foot, 4*foot, 8*foot,
|
||||
16*foot, 32*foot, 50*foot,
|
||||
100*foot, 250*foot, 500*foot,
|
||||
1000*foot, 2500*foot,
|
||||
|
||||
1*mile, 2*mile, 5*mile,
|
||||
10*mile, 25*mile, 50*mile,
|
||||
100*mile
|
||||
]
|
||||
else:
|
||||
#unit unsupported? fall back to metric
|
||||
import FreeCAD as App
|
||||
App.PrintWarning("Lattice Autosize: Unit schema {n} is not yet supported.\n".format(n= unitschema))
|
||||
return getNiceLengths(UnitSystem.SI1)
|
||||
|
||||
def roundToNiceValue(value, nice_value_list = None):
|
||||
if value == 0.0:
|
||||
return 0.0
|
||||
|
||||
if nice_value_list is None:
|
||||
nice_value_list = getNiceLengths()
|
||||
|
||||
bestmatch_logdist = log(1e10)
|
||||
bestmatch = None
|
||||
|
||||
for nice_val in nice_value_list:
|
||||
logdist = abs(log(abs(value)) - log(nice_val))
|
||||
if logdist < bestmatch_logdist:
|
||||
bestmatch_logdist = logdist
|
||||
bestmatch = nice_val
|
||||
|
||||
return math.copysign(bestmatch, value)
|
||||
|
||||
def roundToPrecision(value, precision):
|
||||
if precision < 1e-12:
|
||||
return value
|
||||
return round(value/precision)*precision
|
|
@ -33,6 +33,7 @@ import lattice2CompoundExplorer as LCE
|
|||
import lattice2Markers
|
||||
import lattice2Executer
|
||||
from lattice2ShapeCopy import shallowCopy
|
||||
import lattice2CoinGlue as CoinGlue
|
||||
|
||||
|
||||
def getDefLatticeFaceColor():
|
||||
|
@ -49,11 +50,10 @@ def getDefShapeColor():
|
|||
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.
|
||||
|
||||
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'''
|
||||
no_body: if False, the Lattice object will end up in an active body, and Part2DObject will be used.'''
|
||||
|
||||
body = activeBody()
|
||||
if body and not no_body:
|
||||
|
@ -73,17 +73,16 @@ def makeLatticeFeature(name, AppClass, ViewClass, no_body = False, no_disable_at
|
|||
|
||||
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.'''
|
||||
transform, src = source(documentObject)
|
||||
ret = False
|
||||
if hasattr(documentObject,"isLattice"):
|
||||
if 'On' in documentObject.isLattice:
|
||||
if hasattr(src,'isLattice'):
|
||||
if 'On' in src.isLattice:
|
||||
ret = True
|
||||
if documentObject.isDerivedFrom('App::Placement') or documentObject.isDerivedFrom('PartDesign::CoordinateSystem'):
|
||||
ret = True
|
||||
if documentObject.isDerivedFrom('PartDesign::ShapeBinder'):
|
||||
if len(documentObject.Support) == 1 and documentObject.Support[0][1] == ('',):
|
||||
ret = isObjectLattice(documentObject.Support[0][0])
|
||||
if hasattr(documentObject, 'IAm') and documentObject.IAm == 'PartOMagic.Ghost':
|
||||
ret = isObjectLattice(documentObject.Base)
|
||||
#if documentObject.isDerivedFrom('PartDesign::ShapeBinder'):
|
||||
# if len(documentObject.Support) == 1 and documentObject.Support[0][1] == ('',):
|
||||
# ret = isObjectLattice(documentObject.Support[0][0])
|
||||
#if hasattr(documentObject, 'IAm') and documentObject.IAm == 'PartOMagic.Ghost':
|
||||
# ret = isObjectLattice(documentObject.Base)
|
||||
return ret
|
||||
|
||||
def getMarkerSizeEstimate(ListOfPlacements):
|
||||
|
@ -105,13 +104,15 @@ def getMarkerSizeEstimate(ListOfPlacements):
|
|||
class LatticeFeature(object):
|
||||
"Base object for lattice objects (arrays of placements)"
|
||||
|
||||
attachable = False
|
||||
|
||||
def __init__(self,obj):
|
||||
# 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.Type = self.__module__ + '.' + type(self).__name__
|
||||
|
||||
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.addProperty("App::PropertyLength","MarkerSize","Lattice","Size of placement markers (set to zero for automatic).")
|
||||
|
@ -125,25 +126,115 @@ class LatticeFeature(object):
|
|||
# Auto-On an Auto-Off can be modified when recomputing. Force values are going to stay.
|
||||
|
||||
prop = "ExposePlacement"
|
||||
obj.addProperty("App::PropertyBool",prop,"Lattice","Makes the placement synchronized to Placement property. This will often make this object unmovable. 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.assureProperties(obj, creating_new= True)
|
||||
|
||||
self.updateReadonlyness(obj)
|
||||
if not self.attachable:
|
||||
self.disableAttacher(obj)
|
||||
|
||||
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
|
||||
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."""
|
||||
|
||||
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):
|
||||
'''for overriding by derived classes'''
|
||||
pass
|
||||
|
||||
def execute(self,obj):
|
||||
# please, don't override. Override derivedExecute instead.
|
||||
|
||||
self.assureProperties(obj)
|
||||
|
||||
plms = self.derivedExecute(obj)
|
||||
|
||||
|
@ -156,6 +247,8 @@ class LatticeFeature(object):
|
|||
if markerSize < DistConfusion:
|
||||
markerSize = getMarkerSizeEstimate(plms)
|
||||
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
|
||||
if obj.ExposePlacement:
|
||||
|
@ -185,6 +278,7 @@ class LatticeFeature(object):
|
|||
if obj.isLattice == 'Auto-Off':
|
||||
obj.isLattice = 'Auto-On'
|
||||
|
||||
self.recomputeReferencePlm(obj, plms)
|
||||
else:
|
||||
# DerivedExecute didn't return anything. Thus we assume it
|
||||
# has assigned the shape, and thus we don't do anything.
|
||||
|
@ -192,6 +286,7 @@ class LatticeFeature(object):
|
|||
if obj.isLattice == 'Auto-On':
|
||||
obj.isLattice = 'Auto-Off'
|
||||
|
||||
# i don't remember, wtf is going on here...
|
||||
if obj.ExposePlacement:
|
||||
if obj.Shape.ShapeType == "Compound":
|
||||
children = obj.Shape.childShapes()
|
||||
|
@ -203,7 +298,7 @@ class LatticeFeature(object):
|
|||
else:
|
||||
#nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized.
|
||||
pass
|
||||
return
|
||||
self.updateReadonlyness(obj)
|
||||
|
||||
def derivedExecute(self,obj):
|
||||
'''For overriding by derived class. If this returns a list of placements,
|
||||
|
@ -264,13 +359,36 @@ class LatticeFeature(object):
|
|||
selfobj.MapMode = selfobj.MapMode #trigger attachment, to make it update property states
|
||||
|
||||
def onDocumentRestored(self, selfobj):
|
||||
#override to have attachment!
|
||||
self.disableAttacher(selfobj)
|
||||
if not self.attachable:
|
||||
self.disableAttacher(selfobj)
|
||||
self.assureProperties(selfobj)
|
||||
self.updateReadonlyness(selfobj)
|
||||
|
||||
|
||||
class ViewProviderLatticeFeature(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):
|
||||
'''Don't override. Override derivedInit, please!'''
|
||||
vobj.Proxy = self
|
||||
|
@ -293,13 +411,44 @@ class ViewProviderLatticeFeature(object):
|
|||
FreeCAD.Console.PrintError("__init__() of lattice object view provider is overridden. Please don't! Fix it!\n")
|
||||
except AttributeError as err:
|
||||
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):
|
||||
return getIconPath("Lattice.svg")
|
||||
|
||||
def attach(self, vobj):
|
||||
self.ViewObject = vobj
|
||||
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):
|
||||
return None
|
||||
|
@ -326,10 +475,21 @@ class ViewProviderLatticeFeature(object):
|
|||
# catch all exceptions, because we don't want to prevent deletion if something goes wrong
|
||||
FreeCAD.Console.PrintError("Error in onDelete: " + str(err))
|
||||
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):
|
||||
"""assureProperty(docobj, proptype, propname, defvalue, group, tooltip): adds
|
||||
def assureProperty(docobj, proptype, propname, defvalue, group, tooltip, readonly = False, hidden = False):
|
||||
"""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
|
||||
already exists. Returns True if property was created, or False if not."""
|
||||
|
||||
|
@ -337,7 +497,7 @@ def assureProperty(docobj, proptype, propname, defvalue, group, tooltip):
|
|||
#todo: check type match
|
||||
return False
|
||||
|
||||
docobj.addProperty(proptype, propname, group, tooltip)
|
||||
docobj.addProperty(proptype, propname, group, tooltip, 0, readonly, hidden)
|
||||
if defvalue is not None:
|
||||
setattr(docobj, propname, defvalue)
|
||||
return True
|
||||
|
@ -350,23 +510,60 @@ def makeMoveFromTo(plmFrom, plmTo):
|
|||
from one placement to another placement'''
|
||||
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
|
||||
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.'''
|
||||
if not isObjectLattice(documentObject):
|
||||
if not suppressWarning:
|
||||
lattice2Executer.warning(context, documentObject.Name + " is not a placement or an array of placements. Results may be unexpected.")
|
||||
if documentObject.isDerivedFrom('App::Placement') or documentObject.isDerivedFrom('PartDesign::CoordinateSystem'):
|
||||
return [documentObject.Placement]
|
||||
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):
|
||||
'''splitSelection(sel): splits sel (use getSelectionEx()) into lattices and non-lattices.
|
||||
returns a tuple: (lattices, shapes). lattices is a list, containing all objects
|
||||
that are lattices (placements of arrays of placements). shapes contains all
|
||||
the rest. The lists contain SelectionObjects, not the actual document objects.'''
|
||||
the rest. The lists conain SelectionObjects, not the actual document objects.'''
|
||||
lattices = []
|
||||
shapes = []
|
||||
for selobj in sel:
|
||||
|
@ -375,3 +572,4 @@ def splitSelection(sel):
|
|||
else:
|
||||
shapes.append(selobj)
|
||||
return (lattices, shapes)
|
||||
|
||||
|
|
|
@ -113,8 +113,8 @@ class _BoundBox:
|
|||
obj.CompoundTraversal = ["Use as a whole","Direct children only","Recursive"]
|
||||
obj.CompoundTraversal = "Use as a whole"
|
||||
|
||||
obj.addProperty("App::PropertyBool","Precision","BoundBox","Use precise algorithm (slower).")
|
||||
obj.Precision = False
|
||||
obj.addProperty("App::PropertyBool","Precision","BoundBox","Use precise alorithm (slower).")
|
||||
obj.Precision = True
|
||||
|
||||
obj.addProperty("App::PropertyEnumeration","OrientMode","BoundBox","Choose the orientation of bounding boxes to be made.")
|
||||
obj.OrientMode = ["global","local of compound","local of child","use OrientLink"]
|
||||
|
@ -179,7 +179,7 @@ class _BoundBox:
|
|||
# rotations, some of first three values will be nonzero, and fourth value will
|
||||
# not be equal to 1. While it's enough to compare absolute value of fourth value
|
||||
# to 1, precision is seriously lost in such comparison, so we are checking if
|
||||
# first three values are zero instead.
|
||||
# fisrt three values are zero instead.
|
||||
if abs(Q[0])+abs(Q[1])+abs(Q[2]) < ParaConfusion:
|
||||
orients[i] = None
|
||||
|
||||
|
@ -254,7 +254,7 @@ class _ViewProviderBoundBox:
|
|||
|
||||
def CreateBoundBox(ShapeLink,
|
||||
CompoundTraversal = "Use as a whole",
|
||||
Precision = False,
|
||||
Precision = True,
|
||||
OrientMode = "global",
|
||||
OrientLink = None):
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2016 - Victor Titov (DeepSOIC) *
|
||||
#* Copyright (c) 2018 - Victor Titov (DeepSOIC) *
|
||||
#* <vv.titov@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
|
@ -21,33 +21,29 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
__title__="Group command for interpolation features"
|
||||
__title__="CoinGlue module of FreeCAD add-on Lattice2"
|
||||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
__doc__ = "Glue and conversion routines between coin and freecad"
|
||||
|
||||
import lattice2Resample as Resample
|
||||
import lattice2ScLERP as Sclerp
|
||||
|
||||
import FreeCAD as App
|
||||
if App.GuiUp:
|
||||
import FreeCADGui
|
||||
|
||||
class CommandInterpolateGroup:
|
||||
def GetCommands(self):
|
||||
ret = Resample.exportedCommands
|
||||
return tuple(Sclerp.exportedCommands + Resample.exportedCommands)
|
||||
|
||||
def GetDefaultCommand(self): # return the index of the tuple of the default command.
|
||||
return 0
|
||||
|
||||
def GetResources(self):
|
||||
return { 'MenuText': 'Interpolation features:',
|
||||
'ToolTip': 'Interpolation features (group): creating placements between occurrences.'}
|
||||
|
||||
def IsActive(self): # optional
|
||||
return App.ActiveDocument is not None
|
||||
|
||||
if App.GuiUp:
|
||||
FreeCADGui.addCommand('Lattice2_Interpolate_GroupCommand',CommandInterpolateGroup())
|
||||
|
||||
exportedCommands = ['Lattice2_Interpolate_GroupCommand']
|
||||
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
|
|
@ -1,37 +1,10 @@
|
|||
import FreeCAD as App
|
||||
|
||||
def get_fc_version():
|
||||
"""returns tuple like (0,18,4,16154) for 0.18.4 release, and (0,19,0,18234) for pre builds"""
|
||||
# ['0', '18', '4 (GitTag)', 'git://github.com/FreeCAD/FreeCAD.git releases/FreeCAD-0-18', '2019/10/22 16:53:35', 'releases/FreeCAD-0-18', '980bf9060e28555fecd9e3462f68ca74007b70f8']
|
||||
# ['0', '19', '18234 (Git)', 'git://github.com/FreeCAD/FreeCAD.git master', '2019/09/15 20:43:17', 'master', '3af5d97e9b2a60823815f662aba25422c4bc45bb']
|
||||
strmaj, strmi, strrev = App.Version()[0:3]
|
||||
maj, mi = int(strmaj), int(strmi)
|
||||
submi, rev = 0, 0
|
||||
if '(GitTag)' in strrev:
|
||||
submi = int(strrev.split(" ")[0])
|
||||
elif '(Git)' in strrev:
|
||||
try:
|
||||
rev = int(strrev.split(" ")[0])
|
||||
except Exception as err:
|
||||
App.Console.PrintWarning(u"Lattice2 failed to detect FC version number.\n"
|
||||
" {err}\n".format(err= str(err)))
|
||||
rev = 19207 #assume fairly modern
|
||||
if rev < 100:
|
||||
if mi == 17:
|
||||
rev = 13544
|
||||
elif mi == 18:
|
||||
rev = 16154
|
||||
else:
|
||||
rev = 19207 #assume fairly modern
|
||||
App.Console.PrintWarning(u"Lattice2 failed to detect FC version number: revision is zero / too low, minor version is unexpected.")
|
||||
return (maj, mi, submi, rev)
|
||||
|
||||
|
||||
try:
|
||||
rev_number = get_fc_version()[3]
|
||||
rev_number = int(App.Version()[2].split(" ")[0])
|
||||
except Exception as err:
|
||||
App.Console.PrintError(str(err))
|
||||
rev_number = 10000000
|
||||
del err
|
||||
|
||||
attach_extension_era = rev_number >= 9177
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ def makeOrientationFromLocalAxes(ZAx, XAx = None):
|
|||
YAx.normalize()
|
||||
XAx = YAx.cross(ZAx) # force X perpendicular
|
||||
|
||||
#hacky way of constructing rotation to a local coordinate system:
|
||||
#hacky way of constucting rotation to a local coordinate system:
|
||||
# make matrix,
|
||||
m = App.Matrix()
|
||||
m.A = list(XAx)+[0.0]+list(YAx)+[0.0]+list(ZAx)+[0.0]+[0.0]*3+[1.0]
|
||||
|
@ -129,7 +129,7 @@ def makeOrientationFromLocalAxesUni(priorityString, XAx = None, YAx = None, ZAx
|
|||
# mainAx, secAx, thirdAx, we can't use '=' operator, because '=' reassigns
|
||||
# the reference, and the variables lose linkage. For that purpose,
|
||||
# _assignVector routine was introuced. It assigns the coordinates of the
|
||||
# vector, without replacing references
|
||||
# vector, without replacing referenes
|
||||
|
||||
#force the axes be perpendicular
|
||||
mainAx.normalize()
|
||||
|
@ -160,7 +160,7 @@ def makeOrientationFromLocalAxesUni(priorityString, XAx = None, YAx = None, ZAx
|
|||
if XAx.cross(YAx).dot(ZAx) < 0.0:
|
||||
_assignVector(thirdAx, tmpAx * (-1.0))
|
||||
|
||||
#hacky way of constructing rotation to a local coordinate system:
|
||||
#hacky way of constucting rotation to a local coordinate system:
|
||||
# make matrix,
|
||||
m = App.Matrix()
|
||||
m.A = list(XAx)+[0.0]+list(YAx)+[0.0]+list(ZAx)+[0.0]+[0.0]*3+[1.0]
|
||||
|
|
|
@ -25,16 +25,11 @@ __title__="Lattice Invert object: creates an array of placements from a compound
|
|||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
|
||||
import math
|
||||
|
||||
import FreeCAD as App
|
||||
import Part
|
||||
|
||||
from lattice2Common import *
|
||||
import lattice2BaseFeature
|
||||
import lattice2CompoundExplorer as LCE
|
||||
import lattice2GeomUtils as Utils
|
||||
import lattice2Executer
|
||||
|
||||
# -------------------------- document object --------------------------------------------------
|
||||
|
||||
|
@ -46,8 +41,6 @@ class LatticeInvert(lattice2BaseFeature.LatticeFeature):
|
|||
"The Lattice Invert object"
|
||||
|
||||
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::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.OrientMode = ['invert', 'keep', 'reset']
|
||||
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):
|
||||
# cache stuff
|
||||
base = screen(obj.Base).Shape
|
||||
if not lattice2BaseFeature.isObjectLattice(screen(obj.Base)):
|
||||
lattice2Executer.warning(obj, "Base is not a lattice, but lattice is expected. Results may be unexpected.\n")
|
||||
baseChildren = LCE.AllLeaves(base)
|
||||
|
||||
placements = lattice2BaseFeature.getPlacementsList(obj.Base)
|
||||
|
||||
# dereference
|
||||
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
|
||||
posIsInvert = obj.TranslateMode == 'invert'
|
||||
posIsKeep = obj.TranslateMode == 'keep'
|
||||
|
@ -78,26 +84,29 @@ class LatticeInvert(lattice2BaseFeature.LatticeFeature):
|
|||
outputPlms = [] #list of placements
|
||||
|
||||
# the essence
|
||||
for child in baseChildren:
|
||||
for plm in locplms:
|
||||
pos = App.Vector()
|
||||
ori = App.Rotation()
|
||||
inverted = child.Placement.inverse()
|
||||
inverted = plm.inverse()
|
||||
if posIsInvert:
|
||||
pos = inverted.Base
|
||||
elif posIsKeep:
|
||||
pos = child.Placement.Base
|
||||
pos = plm.Base
|
||||
elif posIsReset:
|
||||
pass
|
||||
|
||||
if oriIsInvert:
|
||||
ori = inverted.Rotation
|
||||
elif oriIsKeep:
|
||||
ori = child.Placement.Rotation
|
||||
ori = plm.Rotation
|
||||
elif oriIsReset:
|
||||
pass
|
||||
|
||||
plm = App.Placement(pos, ori)
|
||||
outputPlms.append(plm)
|
||||
outputPlms.append(App.Placement(pos, ori))
|
||||
|
||||
# re-reference
|
||||
outputPlms = [refplm.multiply(plm) for plm in outputPlms]
|
||||
|
||||
return outputPlms
|
||||
|
||||
|
||||
|
@ -121,6 +130,8 @@ def CreateLatticeInvert(name):
|
|||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.doCommand("f = lattice2Invert.makeLatticeInvert(name='"+name+"')")
|
||||
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"+
|
||||
" child.ViewObject.hide()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
|
|
|
@ -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.")
|
||||
|
||||
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):
|
||||
#validity check
|
||||
nonLattices = []
|
||||
for iArr in range(0, len(obj.Links)):
|
||||
link = obj.Links[iArr]
|
||||
if not lattice2BaseFeature.isObjectLattice(link):
|
||||
nonLattices.append(link.Label)
|
||||
if len(nonLattices) > 0:
|
||||
lattice2Executer.warning(obj, "Only lattice objects are expected to be linked as arrays in JoinArrays. There are "
|
||||
+len(nonLattices)+" objects which are not lattice objects. Results may me unexpected.")
|
||||
|
||||
def derivedExecute(self, selfobj):
|
||||
align = selfobj.AlignReferences
|
||||
#recompute reference placement
|
||||
ref = selfobj.ReferencePlacementOption
|
||||
if ref == 'external':
|
||||
super(JoinArrays, self).recomputeReferencePlm(selfobj, [])
|
||||
elif ref == 'origin':
|
||||
self.setReferencePlm(selfobj, None)
|
||||
elif ref == 'inherit 1st':
|
||||
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
|
||||
listlistPlms = []
|
||||
lengths = []
|
||||
for link in obj.Links:
|
||||
leaves = LCE.AllLeaves(link.Shape)
|
||||
listlistPlms.append([child.Placement for child in leaves])
|
||||
lengths.append(len(leaves))
|
||||
for link in selfobj.Links:
|
||||
plms = lattice2BaseFeature.getPlacementsList(link, context= selfobj, dereferenced= align, torefplm = refplm)
|
||||
listlistPlms.append(plms)
|
||||
lengths.append(len(plms))
|
||||
|
||||
#processing
|
||||
output = [] #list of placements
|
||||
if obj.Interleave:
|
||||
if selfobj.Interleave:
|
||||
for l in lengths[1:]:
|
||||
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
|
||||
|
||||
for iItem in range(0,max(lengths)):
|
||||
|
@ -85,6 +112,7 @@ class JoinArrays(lattice2BaseFeature.LatticeFeature):
|
|||
else:
|
||||
for list in listlistPlms:
|
||||
output.extend(list)
|
||||
|
||||
return output
|
||||
|
||||
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.")}
|
||||
|
||||
def Activated(self):
|
||||
if len(FreeCADGui.Selection.getSelection()) > 1 :
|
||||
CreateJoinArrays(name = "Join")
|
||||
else:
|
||||
mb = QtGui.QMessageBox()
|
||||
mb.setIcon(mb.Icon.Warning)
|
||||
mb.setText(translate("Lattice2_JoinArrays", "Please select at least two lattice objects. Selected lattice objects will be concatenated or interleaved into one array.", None))
|
||||
mb.setWindowTitle(translate("Lattice2_JoinArrays","Bad selection", None))
|
||||
mb.exec_()
|
||||
try:
|
||||
if len(FreeCADGui.Selection.getSelection()) > 1 :
|
||||
CreateJoinArrays(name = "Join")
|
||||
else:
|
||||
infoMessage("Please select at least two lattice objects. Selected lattice objects will be concatenated or interleaved into one array.")
|
||||
except Exception as err:
|
||||
msgError(err)
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument:
|
||||
|
|
|
@ -80,16 +80,17 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
|
|||
obj.Step = 3.0
|
||||
obj.Count = 5.0
|
||||
|
||||
self.assureProperties(obj)
|
||||
|
||||
def updateReadonlyness(self, obj):
|
||||
super(LinearArray,self).updateReadonlyness(obj)
|
||||
link = screen(obj.Link)
|
||||
obj.setEditorMode("Dir", 1 if (link and obj.DirIsDriven) else 0)
|
||||
obj.setEditorMode("Point", 1 if (link and obj.PointIsDriven) else 0)
|
||||
obj.setEditorMode("DirIsDriven", 0 if link else 1)
|
||||
obj.setEditorMode("PointIsDriven", 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()
|
||||
|
||||
def assureGenerator(self, obj):
|
||||
|
@ -101,15 +102,30 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
|
|||
groupname_gen= "Lattice Series Generator",
|
||||
valuesdoc= "List of distances. Distance is measured from Point, along Dir, in millimeters.",
|
||||
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")
|
||||
|
||||
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):
|
||||
self.assureGenerator(obj)
|
||||
self.assureProperties(obj)
|
||||
self.updateReadonlyness(obj)
|
||||
|
||||
# Apply links
|
||||
if screen(obj.Link):
|
||||
|
@ -170,9 +186,30 @@ class LinearArray(lattice2BaseFeature.LatticeFeature):
|
|||
dir.normalize()
|
||||
|
||||
# Make the array
|
||||
def plmByVal(val):
|
||||
return App.Placement(obj.Point + obj.Dir*val, ori)
|
||||
output = [] # list of placements
|
||||
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
|
||||
|
||||
|
@ -196,16 +233,12 @@ def CreateLinearArray(name, mode):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create LinearArray")
|
||||
FreeCADGui.addModule("lattice2LinearArray")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.doCommand("f = lattice2LinearArray.makeLinearArray(name='"+name+"')")
|
||||
if len(sel) == 1:
|
||||
FreeCADGui.doCommand("f.Link = App.ActiveDocument."+sel[0].ObjectName)
|
||||
if sel[0].HasSubObjects:
|
||||
FreeCADGui.doCommand("f.LinkSubelement = '"+sel[0].SubElementNames[0]+"'")
|
||||
FreeCADGui.doCommand("f.GeneratorMode = {mode}".format(mode= repr(mode)))
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.SpanEnd = lattice2Base.Autosize.convenientModelSize()")
|
||||
FreeCADGui.doCommand("f.Step = lattice2Base.Autosize.convenientMarkerSize()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
|
|
@ -21,15 +21,19 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import Part, os
|
||||
import Part
|
||||
import os
|
||||
|
||||
import lattice2CoinGlue as CoinGlue
|
||||
|
||||
__title__="latticeMarkers module for FreeCAD"
|
||||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
__doc__ = "Module for loading marker shapes for Lattice workbench"
|
||||
|
||||
_nullShapeShape = 0
|
||||
_nullShapeShape = None
|
||||
_ShapeDict = {}
|
||||
_NodeDict = {}
|
||||
|
||||
def getShapePath(shapeName):
|
||||
"""
|
||||
|
@ -44,7 +48,7 @@ def getNullShapeShape(scale = 1.0):
|
|||
|
||||
#read shape from file, if not done this before
|
||||
global _nullShapeShape
|
||||
if not _nullShapeShape:
|
||||
if _nullShapeShape is None:
|
||||
_nullShapeShape = Part.Shape()
|
||||
f = open(getShapePath("empty-shape.brep"))
|
||||
_nullShapeShape.importBrep(f)
|
||||
|
@ -73,8 +77,7 @@ def loadShape(shapeID):
|
|||
FreeCAD.Console.PrintError('Failed to load standard shape "'+shapeID+'". \n' + str(err) + '\n')
|
||||
sh = Part.Point() #Create at least something!
|
||||
_ShapeDict[shapeID] = sh
|
||||
return sh
|
||||
|
||||
return sh
|
||||
|
||||
def getPlacementMarker(scale = 1.0, markerID = None):
|
||||
'''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.scale(scale)
|
||||
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)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import lattice2BaseFeature
|
|||
import lattice2Executer
|
||||
from lattice2ShapeCopy import shallowCopy, transformCopy_Smart
|
||||
|
||||
from lattice2PopulateCopies import DereferenceArray
|
||||
from lattice2PopulateCopies import DereferenceArray, REF_MODES
|
||||
|
||||
|
||||
class FeatureUnsupportedError(RuntimeError):
|
||||
|
@ -47,7 +47,7 @@ class ScopeError(RuntimeError):
|
|||
|
||||
|
||||
class MultiTransformSettings(object):
|
||||
selfintersections = False #if True, take care of intersections between occurrences. If False, optimize assuming occurrences do not intersect.
|
||||
selfintersections = False #if True, take care of intersections between occurences. If False, optimize assuming occurences do not intersect.
|
||||
sign_override = +1 #+1 for keep sign, -1 for invert, +2 for force positive, -2 for force negative
|
||||
|
||||
|
||||
|
@ -160,7 +160,7 @@ def applyFeature(baseshape, feature, transforms, mts):
|
|||
if mts.selfintersections:
|
||||
pass #to fuse the shapes to baseshape one by one
|
||||
else:
|
||||
actionshapes = [Part.Compound(actionshapes)] #to fuse all at once, saving for computing intersections between the occurrences of the feature
|
||||
actionshapes = [Part.Compound(actionshapes)] #to fuse all at once, saving for computing intersections between the occurences of the feature
|
||||
|
||||
for actionshape in actionshapes:
|
||||
assert(sign != 0)
|
||||
|
@ -182,7 +182,7 @@ class LatticePDPattern(object):
|
|||
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.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', 'SkipFirstInBody', "Lattice Pattern", "Skip first body feature (which may be used as support for the important features).")
|
||||
|
@ -190,7 +190,7 @@ class LatticePDPattern(object):
|
|||
obj.addProperty('App::PropertyEnumeration', 'SignOverride', "Lattice Pattern", "Use it to change Pockets into Pads.")
|
||||
obj.SignOverride = ['keep', 'invert', 'as additive', 'as subtractive']
|
||||
|
||||
obj.addProperty('App::PropertyBool', 'Selfintersections', "Lattice Pattern", "If True, take care of intersections between occurrences. If False, you get a slight speed boost.")
|
||||
obj.addProperty('App::PropertyBool', 'Selfintersections', "Lattice Pattern", "If True, take care of intersections between occurences. If False, you get a slight speed boost.")
|
||||
|
||||
obj.addProperty('App::PropertyBool', 'Refine', "PartDesign", "If True, remove redundant edges after this operation.")
|
||||
obj.Refine = getParamPDRefine()
|
||||
|
@ -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).')
|
||||
|
||||
|
||||
placements = lattice2BaseFeature.getPlacementsList(selfobj.PlacementsTo, selfobj)
|
||||
placements = DereferenceArray(selfobj, placements, selfobj.PlacementsFrom, selfobj.Referencing)
|
||||
placements = DereferenceArray(selfobj, selfobj.PlacementsTo, selfobj.PlacementsFrom, selfobj.Referencing)
|
||||
if selfobj.Referencing == 'First item' and transforms is None:
|
||||
placements.pop(0) #to not repeat the feature where it was applied already
|
||||
elif selfobj.Referencing == 'Last item' and transforms is None:
|
||||
|
|
|
@ -107,7 +107,7 @@ class LatticeParaSeries(lattice2BaseFeature.LatticeFeature):
|
|||
obj.addProperty("App::PropertyEnumeration","ParameterType","Lattice ParaSeries","Data type of parameter to vary.")
|
||||
obj.ParameterType = ['float','int','string']
|
||||
|
||||
obj.addProperty("App::PropertyString","ParameterRef","Lattice ParaSeries","Reference to the parameter to vary. Syntax: ObjectName.Property. Examples: 'Box.Height'; 'Sketch.Constraints.myLength'.")
|
||||
obj.addProperty("App::PropertyString","ParameterRef","Lattice ParaSeries","Reference to the parameter to vary. Syntax: ObjectName.Property. Examples: 'Box.Height'; 'Sketch.Constaints.myLength'.")
|
||||
|
||||
obj.addProperty("App::PropertyEnumeration","Recomputing","Lattice ParaSeries","Sets recomputing policy.")
|
||||
obj.Recomputing = ["Disabled", "Recompute Once", "Enabled"]
|
||||
|
@ -123,12 +123,16 @@ class LatticeParaSeries(lattice2BaseFeature.LatticeFeature):
|
|||
self.generator.addProperties(groupname= "Lattice ParaSeries",
|
||||
groupname_gen= "Lattice ParaSeries Generator",
|
||||
valuesdoc= "List of parameter values to compute object for.")
|
||||
|
||||
def updateReadonlyness(self, selfobj):
|
||||
super(LatticeParaSeries, self).updateReadonlyness(selfobj)
|
||||
self.assureGenerator(selfobj)
|
||||
self.generator.updateReadonlyness()
|
||||
|
||||
|
||||
def derivedExecute(self,selfobj):
|
||||
# values generator should be functional even if recomputing is disabled, so do it first
|
||||
self.assureGenerator(selfobj)
|
||||
self.generator.updateReadonlyness()
|
||||
self.generator.execute()
|
||||
|
||||
if selfobj.Recomputing == "Disabled":
|
||||
|
|
|
@ -179,12 +179,9 @@ def CreateLatticePlacement(name,mode = 'Custom'):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create Lattice Placement")
|
||||
FreeCADGui.addModule("lattice2Placement")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.doCommand("f = lattice2Placement.makeLatticePlacement(name='"+name+"')")
|
||||
FreeCADGui.doCommand("f.PlacementChoice = '"+mode+"'")
|
||||
FreeCADGui.doCommand("f.Label = '"+mode+"'")
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.MarkerSize = lattice2Base.Autosize.convenientMarkerSize()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCADGui.doCommand("Gui.Selection.addSelection(f)")
|
||||
FreeCADGui.doCommand("f = None")
|
||||
|
@ -195,7 +192,6 @@ def CreateLatticePlacementAx(label, priority, XDir, YDir, ZDir):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create Lattice Placement")
|
||||
FreeCADGui.addModule("lattice2Placement")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
name = "PlacementAx"
|
||||
FreeCADGui.doCommand("f = lattice2Placement.makeLatticePlacementAx(name='"+name+"')")
|
||||
FreeCADGui.doCommand("f.Priority = "+repr(priority))
|
||||
|
@ -206,8 +202,6 @@ def CreateLatticePlacementAx(label, priority, XDir, YDir, ZDir):
|
|||
if ZDir is not None and ZDir.Length > DistConfusion:
|
||||
FreeCADGui.doCommand("f.ZDir_wanted = App.Vector"+repr(tuple(ZDir)))
|
||||
FreeCADGui.doCommand("f.Label = "+repr(label))
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.MarkerSize = lattice2Base.Autosize.convenientMarkerSize()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCADGui.doCommand("Gui.Selection.addSelection(f)")
|
||||
FreeCADGui.doCommand("f = None")
|
||||
|
@ -218,10 +212,7 @@ def CreateLatticePlacementEuler(name):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create Lattice Placement")
|
||||
FreeCADGui.addModule("lattice2Placement")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.doCommand("f = lattice2Placement.makeLatticePlacementEuler(name='"+name+"')")
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.MarkerSize = lattice2Base.Autosize.convenientMarkerSize()")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCADGui.doCommand("Gui.Selection.addSelection(f)")
|
||||
FreeCADGui.doCommand("f = None")
|
||||
|
|
|
@ -75,8 +75,6 @@ class PolarArray(lattice2BaseFeature.LatticeFeature):
|
|||
obj.EndInclusive = False
|
||||
obj.Count = 5
|
||||
|
||||
self.assureProperties(obj)
|
||||
|
||||
def assureGenerator(self, obj):
|
||||
'''Adds an instance of value series generator, if one doesn't exist yet.'''
|
||||
if hasattr(self,"generator"):
|
||||
|
@ -89,21 +87,24 @@ class PolarArray(lattice2BaseFeature.LatticeFeature):
|
|||
self.updateReadonlyness(obj)
|
||||
|
||||
def updateReadonlyness(self, obj):
|
||||
super(PolarArray, self).updateReadonlyness(obj)
|
||||
axislink = screen(obj.AxisLink)
|
||||
obj.setEditorMode("AxisDir", 1 if (axislink and obj.AxisDirIsDriven) else 0)
|
||||
obj.setEditorMode("AxisPoint", 1 if (axislink and obj.AxisPointIsDriven) else 0)
|
||||
obj.setEditorMode("AxisDirIsDriven", 0 if axislink else 1)
|
||||
obj.setEditorMode("AxisPointIsDriven", 0 if axislink else 1)
|
||||
|
||||
self.assureGenerator(obj)
|
||||
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")
|
||||
|
||||
|
||||
def derivedExecute(self,obj):
|
||||
self.assureGenerator(obj)
|
||||
self.assureProperties(obj)
|
||||
self.updateReadonlyness(obj)
|
||||
|
||||
# Apply links
|
||||
if screen(obj.AxisLink):
|
||||
|
|
|
@ -45,7 +45,7 @@ V = App.Vector
|
|||
|
||||
def make():
|
||||
'''make(): makes a PolarArray object.'''
|
||||
obj = lattice2BaseFeature.makeLatticeFeature('PolarArray', PolarArray, ViewProviderPolarArray, no_disable_attacher= True)
|
||||
obj = lattice2BaseFeature.makeLatticeFeature('PolarArray', PolarArray, ViewProviderPolarArray)
|
||||
return obj
|
||||
|
||||
def fetchArc(obj, sub):
|
||||
|
@ -85,7 +85,22 @@ class PolarArray(APlm.AttachableFeature):
|
|||
selfobj.EndInclusive = False
|
||||
selfobj.Step = 55
|
||||
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):
|
||||
'''Adds an instance of value series generator, if one doesn't exist yet.'''
|
||||
if hasattr(self,'generator'):
|
||||
|
@ -95,13 +110,16 @@ class PolarArray(APlm.AttachableFeature):
|
|||
groupname_gen= "Lattice Series Generator",
|
||||
valuesdoc= "List of angles, in degrees.",
|
||||
valuestype= 'App::PropertyFloat')
|
||||
self.updateReadonlyness(selfobj)
|
||||
|
||||
def updateReadonlyness(self, selfobj):
|
||||
super(PolarArray, self).updateReadonlyness(selfobj)
|
||||
|
||||
self.assureGenerator(selfobj)
|
||||
self.generator.updateReadonlyness()
|
||||
|
||||
arc = self.fetchArc(selfobj)
|
||||
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('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)
|
||||
|
@ -113,6 +131,11 @@ class PolarArray(APlm.AttachableFeature):
|
|||
sub = sub[0]
|
||||
#resolve the link
|
||||
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):
|
||||
self.assureGenerator(selfobj)
|
||||
|
@ -189,7 +212,7 @@ class PolarArray(APlm.AttachableFeature):
|
|||
angleplus = -90.0 if on_arc else 0.0
|
||||
mm = -1.0 if selfobj.Reverse else +1.0
|
||||
output = [] # list of placements
|
||||
for ang in values:
|
||||
def plmByVal(ang):
|
||||
localrot = App.Rotation(App.Vector(0,0,1), ang * mm + angleplus)
|
||||
localtransl = localrot.multVec(App.Vector(radius,0,0))
|
||||
localplm = App.Placement(localtransl, localrot)
|
||||
|
@ -200,7 +223,29 @@ class PolarArray(APlm.AttachableFeature):
|
|||
elif is_static:
|
||||
resultplm.Rotation = App.Rotation()
|
||||
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
|
||||
|
||||
|
@ -230,7 +275,6 @@ def CreatePolarArray(genmode = 'SpanN'):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create PolarArray")
|
||||
FreeCADGui.addModule('lattice2PolarArray2')
|
||||
FreeCADGui.addModule('lattice2Executer')
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.doCommand('f = lattice2PolarArray2.make()')
|
||||
FreeCADGui.doCommand("f.GeneratorMode = {mode}".format(mode= repr(genmode)))
|
||||
attached = False
|
||||
|
@ -251,9 +295,6 @@ def CreatePolarArray(genmode = 'SpanN'):
|
|||
.format(lnk= lnk.Name, sub= repr(sub), usearcrange= repr(usearcrange), endinclusive= repr(endinclusive))
|
||||
)
|
||||
attached = True
|
||||
if not attached:
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.Radius = lattice2Base.Autosize.convenientModelSize()/2")
|
||||
FreeCADGui.doCommand('lattice2Executer.executeFeature(f)')
|
||||
if len(sublinks) > 0 and not attached:
|
||||
FreeCADGui.addModule('lattice2AttachablePlacement')
|
||||
|
|
|
@ -34,7 +34,7 @@ from lattice2Common import *
|
|||
import lattice2BaseFeature
|
||||
import lattice2CompoundExplorer as LCE
|
||||
import lattice2Executer
|
||||
from lattice2PopulateCopies import DereferenceArray, throwBody
|
||||
from lattice2PopulateCopies import DereferenceArray, throwBody, REF_MODES
|
||||
import lattice2ShapeCopy as ShapeCopy
|
||||
|
||||
# -------------------------- 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::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.")
|
||||
|
@ -88,11 +88,10 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
|
|||
raise ValueError("Traversal mode not implemented: "+obj.ObjectTraversal)
|
||||
else:
|
||||
objectPlms = lattice2BaseFeature.getPlacementsList(screen(obj.Object), obj)
|
||||
placements = lattice2BaseFeature.getPlacementsList(screen(obj.PlacementsTo), obj)
|
||||
|
||||
|
||||
# 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
|
||||
outputShapes = [] #output list of shapes
|
||||
|
@ -101,6 +100,20 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
|
|||
numChildren = len(objectPlms) if outputIsLattice else len(objectShapes)
|
||||
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
|
||||
for iPlm in range(len(placements)):
|
||||
if iChild == numChildren:
|
||||
|
@ -176,6 +189,11 @@ def CreateLatticePopulateChildren(name, label, shapeObj, latticeObjFrom, lattice
|
|||
FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name)
|
||||
if latticeObjFrom is not None:
|
||||
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.Label = " + repr(label))
|
||||
|
||||
|
@ -286,7 +304,7 @@ class _CommandLatticePopulateChildren_Array:
|
|||
infoMessage("Populate with Children: Build Array",
|
||||
"Populate with Children: Build Array command. Creates an array from children packed into a compound.\n\n"+
|
||||
"Please select a compound, and an array of placements. Then invoke the command. It is also allowed to use another array of placements instead of compound.\n\n"+
|
||||
"Compared to plain 'Populate With Children' command, the placements are treated as being relative to the first placement in the array. As a result, the first child always remains where it was.")
|
||||
"Compared to plain 'Populate With Children' command, the placements are treated as being relative to the first placement in the array. As a result, the first child always remains wher it was.")
|
||||
return
|
||||
cmdPopulate_shapes_nonFromTo("First item")
|
||||
except Exception as err:
|
||||
|
@ -315,7 +333,7 @@ class _CommandLatticePopulateChildren_Move:
|
|||
infoMessage("Move children",
|
||||
"Moved Children command. Creates a compound from another compound, by moving its children.\n\n"+
|
||||
"Each child is moved from one placement to another placement. Please select a compound, then a placement/array to move from, and an array of placements to move to (order matters).\n"+
|
||||
"An array of placements can be used instead of a compound.")
|
||||
"An array of placements can be used insead of a compound.")
|
||||
return
|
||||
cmdPopulate_shapes_FromTo()
|
||||
except Exception as err:
|
||||
|
@ -350,3 +368,4 @@ if FreeCAD.GuiUp:
|
|||
exportedCommands = ['Lattice2_PopulateChildrenGroupCommand']
|
||||
|
||||
# -------------------------- /Gui command --------------------------------------------------
|
||||
|
||||
|
|
|
@ -37,13 +37,16 @@ import lattice2Executer
|
|||
import lattice2ShapeCopy as ShapeCopy
|
||||
|
||||
# ---------------------------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.
|
||||
obj - feature being executed (used for error reporting; can be None)
|
||||
placements - the array, converted into a list of placements.
|
||||
obj - feature being executed
|
||||
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'
|
||||
refmode - a string - enum property item'''
|
||||
|
||||
placements = lattice2BaseFeature.getPlacementsList(lnkTo, obj)
|
||||
plmDeref = App.Placement() #inverse placement of reference (reference is a substitute of origin)
|
||||
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.")
|
||||
|
@ -52,7 +55,7 @@ def DereferenceArray(obj,placements, lnkFrom, refmode):
|
|||
elif refmode == "First item":
|
||||
plmDeref = placements[0].inverse()
|
||||
elif refmode == "Last item":
|
||||
plmDeref = placements[0].inverse()
|
||||
plmDeref = placements[-1].inverse()
|
||||
elif refmode == "Use PlacementsFrom":
|
||||
if lnkFrom is None:
|
||||
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))]
|
||||
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)))
|
||||
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:
|
||||
raise ValueError("Referencing mode not implemented: "+refmode)
|
||||
raise ValueError("Referencing mode not implemented: " + refmode)
|
||||
|
||||
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::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","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.'''
|
||||
super(LatticePopulateCopies, self).assureProperties(obj, creating_new)
|
||||
|
||||
propname = 'OutputCompounding'
|
||||
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.")
|
||||
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."):
|
||||
self.Copying = ShapeCopy.copy_types[0]
|
||||
|
||||
|
||||
def derivedExecute(self,obj):
|
||||
self.assureProperties(obj)
|
||||
|
||||
# cache stuff
|
||||
objectShape = screen(obj.Object).Shape
|
||||
placements = lattice2BaseFeature.getPlacementsList(screen(obj.PlacementsTo), obj)
|
||||
|
||||
outputIsLattice = lattice2BaseFeature.isObjectLattice(screen(obj.Object))
|
||||
|
||||
|
||||
# Pre-collect base placement list, if base is a lattice. For speed.
|
||||
if outputIsLattice:
|
||||
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
|
||||
outputShapes = [] #output list of shapes
|
||||
|
@ -161,18 +183,20 @@ class ViewProviderLatticePopulateCopies(lattice2BaseFeature.ViewProviderLatticeF
|
|||
def getIcon(self):
|
||||
if lattice2BaseFeature.isObjectLattice(self.Object):
|
||||
return getIconPath(
|
||||
{"Origin":"Lattice2_PopulateCopies_Plms_Normal.svg",
|
||||
"First item":"Lattice2_PopulateCopies_Plms_Array.svg",
|
||||
"Last item":"Lattice2_PopulateCopies_Plms_Array.svg",
|
||||
"Use PlacementsFrom":"Lattice2_PopulateCopies_Plms_Move.svg",
|
||||
{'Origin':'Lattice2_PopulateCopies_Plms_Normal.svg',
|
||||
'First item':'Lattice2_PopulateCopies_Plms_Array.svg',
|
||||
'Last item':'Lattice2_PopulateCopies_Plms_Array.svg',
|
||||
'Use PlacementsFrom':'Lattice2_PopulateCopies_Plms_Move.svg',
|
||||
'Array\'s reference':'Lattice2_PopulateCopies_Plms_Ref.svg',
|
||||
}[self.Object.Referencing]
|
||||
)
|
||||
else:
|
||||
return getIconPath(
|
||||
{"Origin":"Lattice2_PopulateCopies_Normal.svg",
|
||||
"First item":"Lattice2_PopulateCopies_Array.svg",
|
||||
"Last item":"Lattice2_PopulateCopies_Array.svg",
|
||||
"Use PlacementsFrom":"Lattice2_PopulateCopies_Move.svg",
|
||||
{'Origin':'Lattice2_PopulateCopies_Normal.svg',
|
||||
'First item':'Lattice2_PopulateCopies_Array.svg',
|
||||
'Last item':'Lattice2_PopulateCopies_Array.svg',
|
||||
'Use PlacementsFrom':'Lattice2_PopulateCopies_Move.svg',
|
||||
'Array\'s reference':'Lattice2_PopulateCopies_Ref.svg',
|
||||
}[self.Object.Referencing]
|
||||
)
|
||||
|
||||
|
@ -199,6 +223,11 @@ def CreateLatticePopulateCopies(name, label, shapeObj, latticeObjFrom, latticeOb
|
|||
FreeCADGui.doCommand("f.PlacementsTo = App.ActiveDocument."+latticeObjTo.Name)
|
||||
if latticeObjFrom is not None:
|
||||
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.Label = " + repr(label))
|
||||
|
||||
|
@ -220,72 +249,83 @@ def CreateLatticePopulateCopies(name, label, shapeObj, latticeObjFrom, latticeOb
|
|||
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.")
|
||||
|
||||
def cmdPopulate_shapes_nonFromTo(refmode):
|
||||
def cmdPopulateCopies():
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
(lattices, shapes) = lattice2BaseFeature.splitSelection(sel)
|
||||
if activeBody() and len(shapes)>0:
|
||||
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:
|
||||
FreeCAD.ActiveDocument.openTransaction("Populate with copies")
|
||||
# move shapes from to
|
||||
FreeCAD.ActiveDocument.openTransaction("Transport")
|
||||
latticeFrom = lattices[0]
|
||||
latticeTo = lattices[1]
|
||||
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)
|
||||
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:
|
||||
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"
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : getIconPath("Lattice2_PopulateCopies_Normal.svg"),
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_PopulateCopies","Populate with copies"),
|
||||
return {'Pixmap' : getIconPath("Lattice2_PopulateCopies.svg"),
|
||||
'MenuText': "Populate with copies",
|
||||
'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):
|
||||
try:
|
||||
if len(FreeCADGui.Selection.getSelection())==0:
|
||||
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"+
|
||||
"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
|
||||
cmdPopulate_shapes_nonFromTo("Origin")
|
||||
cmdPopulateCopies()
|
||||
except Exception as err:
|
||||
msgError(err)
|
||||
|
||||
|
@ -296,85 +336,9 @@ class _CommandLatticePopulateCopies_Normal:
|
|||
return False
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Lattice2_PopulateCopies_Normal', _CommandLatticePopulateCopies_Normal())
|
||||
FreeCADGui.addCommand('Lattice2_PopulateCopies', CommandLatticePopulateCopies())
|
||||
|
||||
class _CommandLatticePopulateCopies_Array:
|
||||
"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']
|
||||
exportedCommands = ['Lattice2_PopulateCopies']
|
||||
|
||||
# -------------------------- /Gui command --------------------------------------------------
|
||||
|
||||
|
|
|
@ -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.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):
|
||||
#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
|
||||
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.")
|
||||
leaves = LCE.AllLeaves(toolShape)
|
||||
points = [Part.Vertex(leaf.Placement.Base) for leaf in leaves]
|
||||
lattice2Executer.warning(obj, "A lattice object was provided as Tool. It will be converted into points; orientations will be ignored.")
|
||||
plms = lattice2BaseFeature.getPlacementsList(obj.Tool)
|
||||
points = [Part.Vertex(plm.Base) for plm in plms]
|
||||
toolShape = Part.makeCompound(points)
|
||||
|
||||
leaves = LCE.AllLeaves(screen(obj.Base).Shape)
|
||||
input = [leaf.Placement for leaf in leaves]
|
||||
ref = obj.ReferencePlacementOption
|
||||
|
||||
input = lattice2BaseFeature.getPlacementsList(obj.Base, obj)
|
||||
if ref == 'projected':
|
||||
input.append(lattice2BaseFeature.getReferencePlm(obj.Base))
|
||||
|
||||
output = [] #variable to receive the final list of placements
|
||||
|
||||
|
@ -170,6 +186,17 @@ class LatticeProjectArray(lattice2BaseFeature.LatticeFeature):
|
|||
if not isMultiSol:
|
||||
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
|
||||
|
||||
|
||||
|
@ -185,11 +212,11 @@ class ViewProviderProjectArray(lattice2BaseFeature.ViewProviderLatticeFeature):
|
|||
def CreateLatticeProjectArray(name):
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
|
||||
# selection order independence logic (lattice object and generic shape stencil can be told apart)
|
||||
# selection order independece logic (lattice object and generic shape stencil can be told apart)
|
||||
iLtc = 0 #index of lattice object in selection
|
||||
iStc = 1 #index of stencil object in selection
|
||||
for i in range(0,len(sel)):
|
||||
if lattice2BaseFeature.isObjectLattice(sel[i]):
|
||||
if lattice2BaseFeature.isObjectLattice(sel[i].Object):
|
||||
iLtc = i
|
||||
iStc = i-1 #this may give negative index, but python accepts negative indexes
|
||||
break
|
||||
|
|
|
@ -365,6 +365,7 @@ class _CommandTouch:
|
|||
def GetResources(self):
|
||||
return {'Pixmap' : getIconPath("Lattice2_RecomputeLocker_Touch.svg"),
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_RecomputeLocker","Touch selected features"),
|
||||
'Accel': "Shift+F5",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_RecomputeLocker","Touch selected features: mark selected features as needing recomputing."),
|
||||
'CmdType':"ForEdit"}
|
||||
|
||||
|
@ -406,14 +407,8 @@ exportedCommands = [
|
|||
"Lattice2_RecomputeLocker_ForceRecompute",
|
||||
"Lattice2_RecomputeLocker_Touch"
|
||||
]
|
||||
try:
|
||||
if float(App.Version()[1]) >= 17.0:
|
||||
exportedCommands.remove("Lattice2_RecomputeLocker_MakeFeature")
|
||||
except Exception as err:
|
||||
App.Console.PrintWarning("Failed to parse version string: {v}".format(v= App.Version()[1]))
|
||||
#assume modern
|
||||
if int(App.Version()[1]) >= 17:
|
||||
exportedCommands.remove("Lattice2_RecomputeLocker_MakeFeature")
|
||||
|
||||
|
||||
class CommandRecomputeGroup:
|
||||
def GetCommands(self):
|
||||
|
|
|
@ -106,7 +106,7 @@ class LatticeResample(lattice2BaseFeature.LatticeFeature):
|
|||
QArrays[iQ].append( Q[iQ] )
|
||||
prevQ = Q
|
||||
|
||||
# construct function objects
|
||||
# constuct function objects
|
||||
if posIsInterpolate:
|
||||
FX = LIU.InterpolateF(IArray,XArray)
|
||||
FY = LIU.InterpolateF(IArray,YArray)
|
||||
|
|
257
lattice2Resample2.py
Normal file
257
lattice2Resample2.py
Normal 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 --------------------------------------------------
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2019 - 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 ScLERP object: interpolation between two placements."
|
||||
__author__ = "DeepSOIC"
|
||||
|
||||
import FreeCAD as App
|
||||
import Part
|
||||
|
||||
from lattice2Common import *
|
||||
import lattice2BaseFeature
|
||||
import lattice2Executer
|
||||
from lattice2ValueSeriesGenerator import ValueSeriesGenerator
|
||||
|
||||
# -------------------------- document object --------------------------------------------------
|
||||
def makeLatticeScLERP(name):
|
||||
'''makeLatticeScLERP(name): makes a LatticeScLERP object.'''
|
||||
return lattice2BaseFeature.makeLatticeFeature(name, LatticeScLERP, ViewProviderLatticeScLERP)
|
||||
|
||||
class LatticeScLERP(lattice2BaseFeature.LatticeFeature):
|
||||
"The Lattice ScLERP object"
|
||||
|
||||
def derivedInit(self,host):
|
||||
host.addProperty("App::PropertyLink","Placement1Ref","Lattice ScLERP","First placement, or an array of two placements to interpolate between.")
|
||||
host.addProperty("App::PropertyLink","Placement2Ref","Lattice ScLERP","Second placement to interpolate between.")
|
||||
host.addProperty("App::PropertyBool","Shorten","Lattice ScLERP","Use shortest path. (if not, and angle difference of two placement exceeds 180 degrees, longer path will be taken)")
|
||||
host.Shorten = True
|
||||
|
||||
self.assureGenerator(host)
|
||||
host.ValuesSource = "Generator"
|
||||
host.GeneratorMode = "SpanN"
|
||||
host.EndInclusive = True
|
||||
host.SpanStart = 0.0
|
||||
host.SpanEnd = 1.0
|
||||
host.Step = 1.0/11
|
||||
host.Count = 11
|
||||
|
||||
def assureGenerator(self, host):
|
||||
'''Adds an instance of value series generator, if one doesn't exist yet.'''
|
||||
if hasattr(self,"generator"):
|
||||
return
|
||||
self.generator = ValueSeriesGenerator(host)
|
||||
self.generator.addProperties(groupname= "Lattice Array",
|
||||
groupname_gen= "Lattice Series Generator",
|
||||
valuesdoc= "List of parameter values. Values should be in range 0..1 for interpolation, and can be outside for extrapolation.",
|
||||
valuestype= "App::PropertyFloat")
|
||||
|
||||
def updateReadonlyness(self, host):
|
||||
super(LatticeScLERP, self).updateReadonlyness(host)
|
||||
|
||||
self.assureGenerator(host)
|
||||
self.generator.updateReadonlyness()
|
||||
|
||||
#host.setEditorMode('ReferenceValue', 0 if host.ReferencePlacementOption == 'at custom value' else 2)
|
||||
|
||||
def derivedExecute(self,host):
|
||||
self.assureGenerator(host)
|
||||
|
||||
self.generator.execute()
|
||||
values = [float(strv) for strv in host.Values]
|
||||
|
||||
input = lattice2BaseFeature.getPlacementsList(host.Placement1Ref)
|
||||
if host.Placement2Ref is not None:
|
||||
input.extend(lattice2BaseFeature.getPlacementsList(host.Placement2Ref))
|
||||
|
||||
if len(input) != 2:
|
||||
raise ValueError("Need exactly 2 placements. {n} provided.".format(n= len(input)))
|
||||
|
||||
plm1, plm2 = input
|
||||
|
||||
# construct interpolation functions
|
||||
# prepare lists of input samples
|
||||
|
||||
def plmByVal(val):
|
||||
return plm1.sclerp(plm2, val, host.Shorten)
|
||||
|
||||
output = [plmByVal(val) for val in values]
|
||||
|
||||
## update reference placement
|
||||
#ref = host.ReferencePlacementOption
|
||||
#if ref == 'external':
|
||||
# pass
|
||||
#elif ref == 'origin':
|
||||
# self.setReferencePlm(host, None)
|
||||
#elif ref == 'inherit':
|
||||
# self.setReferencePlm(host, lattice2BaseFeature.getReferencePlm(host.Base))
|
||||
#elif ref == 'SpanStart':
|
||||
# self.setReferencePlm(host, plmByVal(float(host.SpanStart)))
|
||||
#elif ref == 'SpanEnd':
|
||||
# self.setReferencePlm(host, plmByVal(float(host.SpanEnd)))
|
||||
#elif ref == 'at custom value':
|
||||
# self.setReferencePlm(host, plmByVal(float(host.ReferenceValue)))
|
||||
#elif ref == 'first placement':
|
||||
# self.setReferencePlm(host, output[0])
|
||||
#elif ref == 'last placement':
|
||||
# self.setReferencePlm(host, output[-1])
|
||||
#else:
|
||||
# raise NotImplementedError("Reference option not implemented: " + ref)
|
||||
#
|
||||
return output
|
||||
|
||||
|
||||
class ViewProviderLatticeScLERP(lattice2BaseFeature.ViewProviderLatticeFeature):
|
||||
|
||||
def getIcon(self):
|
||||
return getIconPath('Lattice2_Resample.svg')
|
||||
|
||||
def claimChildren(self):
|
||||
return [child for child in [self.Object.Placement1Ref,self.Object.Placement2Ref] if child is not None]
|
||||
|
||||
|
||||
# -------------------------- /document object --------------------------------------------------
|
||||
|
||||
# -------------------------- Gui command --------------------------------------------------
|
||||
|
||||
def CreateLatticeScLERP(name):
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
FreeCAD.ActiveDocument.openTransaction("Create LatticeScLERP")
|
||||
FreeCADGui.addModule("lattice2ScLERP")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.doCommand("f = lattice2ScLERP.makeLatticeScLERP(name='"+name+"')")
|
||||
FreeCADGui.doCommand("f.Placement1Ref = App.ActiveDocument."+sel[0].ObjectName)
|
||||
if len(sel) > 1:
|
||||
FreeCADGui.doCommand("f.Placement2Ref = App.ActiveDocument."+sel[1].ObjectName)
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
||||
class CommandLatticeScLERP:
|
||||
"Command to create LatticeScLERP feature"
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : getIconPath("Lattice2_ScLERP.svg"),
|
||||
'MenuText': "Helical interpolation (ScLERP)",
|
||||
'Accel': "",
|
||||
'ToolTip': "Helical interpolation (ScLERP): divides the move from one placement to another into a number of equal-transform steps."}
|
||||
|
||||
def Activated(self):
|
||||
try:
|
||||
if len(FreeCADGui.Selection.getSelection()) in [1, 2] :
|
||||
CreateLatticeScLERP(name = "ScLERP")
|
||||
else:
|
||||
infoMessage(
|
||||
"Helical interpolation (ScLERP)",
|
||||
"Lattice Helical interpolation (ScLERP) command. Interpolates between two placements using ScLERP."
|
||||
" It cretes a helical path between two placements, so that the placement moves and rotates by an"
|
||||
" equal transform for each step. \n\n"
|
||||
"Please select two placements, first. It can be two placements in one object, or two single placement objects."
|
||||
)
|
||||
except Exception as err:
|
||||
msgError(err)
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Lattice2_ScLERP', CommandLatticeScLERP())
|
||||
|
||||
exportedCommands = ['Lattice2_ScLERP'] if hasattr(App.Placement, 'sclerp') else []
|
||||
|
||||
# -------------------------- /Gui command --------------------------------------------------
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
__title__= "Lattice ShapeInfo feature for FreeCAD"
|
||||
__author__ = "DeepSOIC"
|
||||
__doc__ = "Shape info feature is for getting info on a shape and exposing it in form of properties, that are usable from expressions."
|
||||
__doc__ = "Shape info feature is for getting info on a shape and exposing it in form of properties, that are useable from expressions."
|
||||
|
||||
from lattice2Common import *
|
||||
import lattice2BaseFeature as LBF
|
||||
|
|
|
@ -38,7 +38,7 @@ __url__ = ""
|
|||
|
||||
|
||||
def findFont(font_file_name):
|
||||
'''checks for existence of the file in a few locations and returns the full path of the first one found'''
|
||||
'''checks for existance of the file in a few locations and returns the full path of the first one found'''
|
||||
|
||||
import os
|
||||
|
||||
|
@ -105,7 +105,7 @@ class LatticeShapeString:
|
|||
self.makeFoolObj(obj)
|
||||
foolObj = self.foolObj
|
||||
|
||||
#add Draft ShapeString's properties to document object in possession of our LatticeShapeString
|
||||
#add Draft ShapeString's properties to document object in posession of our LatticeShapeString
|
||||
for (proptype, propname, group, hint) in foolObj.properties:
|
||||
if propname != "String": #we'll define our own string property
|
||||
obj.addProperty(proptype,propname,"Lattice ShapeString",hint)
|
||||
|
@ -219,10 +219,8 @@ class LatticeShapeString:
|
|||
scale = 1.0
|
||||
obj.Shape = markers.getNullShapeShape(scale)
|
||||
raise ValueError('No strings were converted into shapes') #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing.
|
||||
result = Part.makeCompound(shapes)
|
||||
result.Placement = obj.Placement
|
||||
obj.Shape = result
|
||||
|
||||
|
||||
obj.Shape = Part.makeCompound(shapes)
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
@ -256,13 +254,9 @@ def CreateLatticeShapeString(name):
|
|||
FreeCAD.ActiveDocument.openTransaction("Create LatticeShapeString")
|
||||
FreeCADGui.addModule("lattice2ShapeString")
|
||||
FreeCADGui.addModule("lattice2Executer")
|
||||
FreeCADGui.addModule("lattice2Base.Autosize")
|
||||
FreeCADGui.doCommand("f = lattice2ShapeString.makeLatticeShapeString(name='"+name+"')")
|
||||
if len(sel) == 1:
|
||||
FreeCADGui.doCommand("f.ArrayLink = FreeCADGui.Selection.getSelection()[0]")
|
||||
else:
|
||||
FreeCADGui.doCommand("f.Placement.Base = lattice2Base.Autosize.convenientPosition()")
|
||||
FreeCADGui.doCommand("f.Size = lattice2Base.Autosize.convenientModelSize()/10")
|
||||
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
|
||||
FreeCADGui.doCommand("f = None")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
|
|
@ -58,7 +58,7 @@ class LatticeSubLink:
|
|||
self.assureProperties(obj)
|
||||
|
||||
def assureProperties(self, selfobj):
|
||||
assureProperty(selfobj, "App::PropertyEnumeration","Looping", ["Single"] + LSS.LOOP_MODES, "Lattice SubLink", "Sets whether to collect just the element, or all similar from array.")
|
||||
assureProperty(selfobj, "App::PropertyEnumeration","Looping", ["Single"] + LSS.LOOP_MODES, "Lattice SubLink", "Sets wether to collect just the element, or all similar from array.")
|
||||
assureProperty(selfobj, "App::PropertyEnumeration","CompoundTraversal", LSS.TRAVERSAL_MODES, "Lattice SubLink", "Sets how to unpack compounds if Looping is not 'Single'.")
|
||||
assureProperty(selfobj, "App::PropertyLinkSub", "SubLink", sublinkFromApart(screen(selfobj.Object), selfobj.SubNames), "Lattice SubLink", "Mirror of Object+SubNames properties")
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ element_extractors = {
|
|||
|
||||
def getIndexesIntoList(element, list_of_shapes):
|
||||
"""Finds this element in shapes in list_of_shapes. This is a generator function (to be
|
||||
used if there are multiple occurrences of the element).
|
||||
used if there are multiple occurences of the element).
|
||||
[(index_into_list, element_type_string, subelement_index), ...]"""
|
||||
|
||||
element_type_string = element.ShapeType
|
||||
|
|
|
@ -105,7 +105,7 @@ class CommandSubstituteObject:
|
|||
except Exception as err:
|
||||
mb = QtGui.QMessageBox()
|
||||
mb.setIcon(mb.Icon.Warning)
|
||||
mb.setText(translate("Lattice2_SubstituteObject", "An error occurred while substituting object:", None)+ u"\n"
|
||||
mb.setText(translate("Lattice2_SubstituteObject", "An error occured while substituting object:", None)+ u"\n"
|
||||
+ str(err))
|
||||
mb.setWindowTitle(translate("Lattice2_SubstituteObject","Error", None))
|
||||
mb.exec_()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2015 - Victor Titov (DeepSOIC) *
|
||||
#* <vv.titov@gmail.com> *
|
||||
#* <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) *
|
||||
|
@ -44,26 +44,26 @@ class ValueSeriesGenerator:
|
|||
self.gen_laws = ['Linear','Exponential']
|
||||
self.alignment_modes = ['Low', 'Center', 'High', 'Justify', 'Mirrored']
|
||||
self.readonlynessDict = {} # key = property name (string). Value = boolean (True == writable, non-readonly). Stores property read-only status requested by external code.
|
||||
|
||||
|
||||
|
||||
|
||||
def addProperties(self, groupname, groupname_gen, valuesdoc, valuestype = 'App::PropertyFloat'):
|
||||
# _addProperty(proptype , propname , defvalue, group, tooltip)
|
||||
|
||||
# first, try to guess interface version. If we are re-adding properties to old feature,
|
||||
# it already has some other properties, but not Version. So we should default to 0
|
||||
# in this case. Otherwise the Version property already exists, so default doesn't matter;
|
||||
|
||||
# first, try to guess interface version. If we are re-adding properties to old feature,
|
||||
# it already has some other properties, but not Version. So we should default to 0
|
||||
# in this case. Therwise the Version property already exists, so default desn't matter;
|
||||
# or we are creating a new generator, so default to 1.
|
||||
self._addProperty("App::PropertyInteger" ,"VSGVersion" , 0 if hasattr(self.documentObject, "Values") else 1 , groupname_gen, "Interface version")
|
||||
self.documentObject.setEditorMode("VSGVersion", 2) #hide this property
|
||||
|
||||
|
||||
self._addProperty("App::PropertyStringList" ,"Values" , None, groupname, valuesdoc)
|
||||
self._addProperty("App::PropertyEnumeration","ValuesSource" , self.source_modes, groupname, "Select where to take the value series from.")
|
||||
self._addProperty("App::PropertyLink" ,"SpreadsheetLink", None, groupname, "Link to spreadsheet to take values from.")
|
||||
self._addProperty("App::PropertyString" ,"CellStart" , 'A1', groupname, "Starting cell of first value (the rest are scanned downwards till an empty cell is encountered)")
|
||||
|
||||
|
||||
self._addProperty("App::PropertyEnumeration","GeneratorMode" , self.gen_modes, groupname_gen,"")
|
||||
self._addProperty("App::PropertyEnumeration","DistributionLaw", self.gen_laws, groupname_gen,"")
|
||||
|
||||
|
||||
self._addProperty(valuestype ,"SpanStart" , 1.0, groupname_gen, "Starting value for value series generator")
|
||||
self._addProperty(valuestype ,"SpanEnd" , 7.0, groupname_gen, "Ending value for value series generator")
|
||||
self._addProperty("App::PropertyBool" ,"EndInclusive" , True, groupname_gen, "If True, the last value in series will equal SpanEnd. If False, the value equal to SpanEnd will be dropped.")
|
||||
|
@ -71,7 +71,7 @@ class ValueSeriesGenerator:
|
|||
self._addProperty("App::PropertyFloat" ,"Step" , 1.0, groupname_gen, "Step for value generator. For exponential law, it is a natural logarithm of change ratio.") # using float for Step, because step's unit depends n selected distribution law
|
||||
self._addProperty("App::PropertyFloat" ,"Count" , 7.0, groupname_gen, "Number of values to generate")
|
||||
self._addProperty("App::PropertyFloat" ,"Offset" , 0.0, groupname_gen, "Extra offset for the series, expressed as fraction of step.")
|
||||
|
||||
|
||||
def _addProperty(self, proptype, propname, defvalue, group, tooltip):
|
||||
if hasattr(self.documentObject, propname):
|
||||
return
|
||||
|
@ -83,15 +83,15 @@ class ValueSeriesGenerator:
|
|||
obj = self.documentObject
|
||||
m = obj.GeneratorMode
|
||||
src = obj.ValuesSource
|
||||
|
||||
|
||||
self._setPropertyWritable("Values" , src == "Values Property" )
|
||||
self._setPropertyWritable("ValuesSource" , True )
|
||||
self._setPropertyWritable("SpreadsheetLink" , src == "Spreadsheet" )
|
||||
self._setPropertyWritable("CellStart" , src == "Spreadsheet" )
|
||||
|
||||
|
||||
self._setPropertyWritable("GeneratorMode" , not self.isPropertyControlledByGenerator("GeneratorMode" ) )
|
||||
self._setPropertyWritable("DistributionLaw" , not self.isPropertyControlledByGenerator("DistributionLaw") )
|
||||
|
||||
|
||||
self._setPropertyWritable("SpanStart" , not self.isPropertyControlledByGenerator("SpanStart" ) )
|
||||
self._setPropertyWritable("SpanEnd" , not self.isPropertyControlledByGenerator("SpanEnd" ) )
|
||||
self._setPropertyWritable("EndInclusive" , not self.isPropertyControlledByGenerator("EndInclusive" ) )
|
||||
|
@ -99,19 +99,19 @@ class ValueSeriesGenerator:
|
|||
self._setPropertyWritable("Step" , not self.isPropertyControlledByGenerator("Step" ) )
|
||||
self._setPropertyWritable("Count" , not self.isPropertyControlledByGenerator("Count" ) )
|
||||
self._setPropertyWritable("Offset" , not self.isPropertyControlledByGenerator("Offset" ) )
|
||||
|
||||
|
||||
def isPropertyControlledByGenerator(self, propname):
|
||||
obj = self.documentObject
|
||||
if not hasattr(obj, propname):
|
||||
raise AttributeError(obj.Name+": has no property named "+propname)
|
||||
|
||||
|
||||
m = obj.GeneratorMode
|
||||
|
||||
genOn = obj.ValuesSource == "Generator"
|
||||
if not genOn:
|
||||
return False
|
||||
return False
|
||||
|
||||
if propname == "SpanStart":
|
||||
if propname == "SpanStart":
|
||||
return False
|
||||
elif propname == "SpanEnd":
|
||||
return False
|
||||
|
@ -123,21 +123,21 @@ class ValueSeriesGenerator:
|
|||
return False
|
||||
|
||||
def setPropertyWritable(self, propname, bool_writable):
|
||||
'''setPropertyWritable(self, propname, bool_writable): Use to force a property read-only
|
||||
(for example, when the property is driven by a link). If set to be writable, the read-onlyness
|
||||
'''setPropertyWritable(self, propname, bool_writable): Use to force a property read-only
|
||||
(for example, when the property is driven by a link). If set to be writable, the read-onlyness
|
||||
will be set according to series generator logic.'''
|
||||
self.readonlynessDict[propname] = bool_writable
|
||||
|
||||
|
||||
def _setPropertyWritable(self, propname, bool_writable, suppress_warning = False):
|
||||
if propname in self.readonlynessDict:
|
||||
bool_writable = bool_writable and self.readonlynessDict[propname]
|
||||
bool_writable = bool_writable and self.readonlynessDict[propname]
|
||||
self.documentObject.setEditorMode(propname, 0 if bool_writable else 1)
|
||||
|
||||
|
||||
def execute(self):
|
||||
obj = self.documentObject #shortcut
|
||||
|
||||
|
||||
values = [] #list to be filled with values, that are giong to be written to obj.Values
|
||||
|
||||
|
||||
if obj.ValuesSource == "Generator":
|
||||
#read out span and convert it to linear law
|
||||
if obj.DistributionLaw == 'Linear':
|
||||
|
@ -147,13 +147,13 @@ class ValueSeriesGenerator:
|
|||
elif obj.DistributionLaw == 'Exponential':
|
||||
vSign = 1 if obj.SpanStart > 0.0 else -1.0
|
||||
vStart = math.log(obj.SpanStart * vSign)
|
||||
if obj.SpanEnd * vSign < ParaConfusion:
|
||||
if obj.SpanEnd * vSign < ParaConfusion:
|
||||
raise ValueError(obj.Name+": Wrong SpanEnd value. It is either zero, or of different sign compared to SpanStart. In exponential distribution, it is not allowed.")
|
||||
vEnd = math.log(obj.SpanEnd * vSign)
|
||||
vStep = float(obj.Step)
|
||||
else:
|
||||
raise ValueError(obj.Name+": distribution law not implemented: "+obj.DistributionLaw)
|
||||
|
||||
|
||||
if obj.GeneratorMode == 'SpanN':
|
||||
n = obj.Count
|
||||
if obj.EndInclusive:
|
||||
|
@ -188,16 +188,16 @@ class ValueSeriesGenerator:
|
|||
pass
|
||||
else:
|
||||
raise ValueError(obj.Name+": Generator mode "+obj.GeneratorMode+" is not implemented")
|
||||
|
||||
# Generate the actual array. We can use Step and N directly to
|
||||
|
||||
# Generate the actual array. We can use Step and N directly to
|
||||
# completely avoid mode logic, since we had updated them
|
||||
|
||||
|
||||
# cache properties into variables
|
||||
# vStart,vEnd are already in sync
|
||||
vStep = float(obj.Step)
|
||||
vOffset = float(obj.Offset)
|
||||
n = int(obj.Count)
|
||||
|
||||
|
||||
# Generate the values
|
||||
if obj.GeneratorMode == 'Random':
|
||||
import random
|
||||
|
@ -221,9 +221,9 @@ class ValueSeriesGenerator:
|
|||
if n_tmp == 0:
|
||||
n_tmp = 1 #justify failed!
|
||||
vStep_justified = (vEnd - vStart)/n_tmp
|
||||
|
||||
|
||||
list_evenDistrib = [vStart + vOffset*vStep + alignment_offset + vStep_justified*i for i in range(0, n)]
|
||||
|
||||
|
||||
#post-process alignment
|
||||
if obj.Alignment == "Mirrored":
|
||||
new_list = []
|
||||
|
@ -232,7 +232,7 @@ class ValueSeriesGenerator:
|
|||
if abs(v) > 1e-12:
|
||||
new_list.append(-v)
|
||||
list_evenDistrib = new_list
|
||||
|
||||
|
||||
if obj.DistributionLaw == 'Linear':
|
||||
values = list_evenDistrib
|
||||
elif obj.DistributionLaw == 'Exponential':
|
||||
|
@ -250,7 +250,7 @@ class ValueSeriesGenerator:
|
|||
col = addr[0:1]
|
||||
row = addr[1:]
|
||||
row = int(row)
|
||||
|
||||
|
||||
#loop until the value can't be read out
|
||||
values = []
|
||||
spsh = screen(obj.SpreadsheetLink)
|
||||
|
@ -264,7 +264,8 @@ class ValueSeriesGenerator:
|
|||
pass
|
||||
else:
|
||||
raise ValueError(obj.Name+": values source mode not implemented: "+obj.ValuesSource)
|
||||
|
||||
|
||||
# finally. Fill in the values.
|
||||
if obj.ValuesSource != "Values Property":
|
||||
obj.Values = [str(v) for v in values]
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2015 - 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 Recompute Locker: hack to manual recompute of documents."
|
||||
__author__ = "DeepSOIC"
|
||||
__url__ = ""
|
||||
|
||||
import FreeCAD as App
|
||||
if App.GuiUp:
|
||||
import FreeCADGui as Gui
|
||||
|
||||
from lattice2Common import *
|
||||
import lattice2BaseFeature as LBF
|
||||
import lattice2CompoundExplorer as LCE
|
||||
|
||||
try:
|
||||
import Show
|
||||
except ImportError:
|
||||
Show = None
|
||||
try:
|
||||
from Show.SceneDetail import SceneDetail
|
||||
except ImportError:
|
||||
SceneDetail = None
|
||||
|
||||
from copy import copy
|
||||
|
||||
class SDParameter(SceneDetail if SceneDetail is not None else object):
|
||||
"""SDParameter(param_path, param_name, param_type, param_val = None): Plugin for TempoVis for changing a parameter."""
|
||||
class_id = 'SDParameter'
|
||||
mild_restore = True
|
||||
param_path = ''
|
||||
param_name = ''
|
||||
param_type = ''
|
||||
|
||||
def __init__(self, param_path, param_name, param_type, param_val = None):
|
||||
self.key = '{param_path}/[{param_type}]{param_name}'.format(**vars())
|
||||
self.param_path = param_path
|
||||
self.param_name = param_name
|
||||
self.param_type = param_type
|
||||
if param_val is not None:
|
||||
self.data = param_val
|
||||
|
||||
def scene_value(self):
|
||||
import FreeCAD as App
|
||||
hgrp = App.ParamGet(self.param_path)
|
||||
getter, def1, def2 = {
|
||||
'Bool' : (hgrp.GetBool , True, False),
|
||||
'Float' : (hgrp.GetFloat , 1.0, 2.0 ),
|
||||
'Int' : (hgrp.GetInt , 1, 2 ),
|
||||
'String' : (hgrp.GetString , 'a', 'b' ),
|
||||
'Unsigned': (hgrp.GetUnsigned, 1, 2 ),
|
||||
}[self.param_type]
|
||||
val1 = getter(self.param_name, def1)
|
||||
val2 = getter(self.param_name, def2)
|
||||
absent = val1 == def1 and val2 == def2
|
||||
return val1 if not absent else None
|
||||
|
||||
def apply_data(self, val):
|
||||
import FreeCAD as App
|
||||
hgrp = App.ParamGet(self.param_path)
|
||||
setter = {
|
||||
'Bool' : (hgrp.SetBool ),
|
||||
'Float' : (hgrp.SetFloat ),
|
||||
'Int' : (hgrp.SetInt ),
|
||||
'String' : (hgrp.SetString ),
|
||||
'Unsigned': (hgrp.SetUnsigned),
|
||||
}[self.param_type]
|
||||
deleter = {
|
||||
'Bool' : (hgrp.RemBool ),
|
||||
'Float' : (hgrp.RemFloat ),
|
||||
'Int' : (hgrp.RemInt ),
|
||||
'String' : (hgrp.RemString ),
|
||||
'Unsigned': (hgrp.RemUnsigned),
|
||||
}[self.param_type]
|
||||
if val is None:
|
||||
deleter(self.param_name)
|
||||
else:
|
||||
setter(self.param_name, val)
|
||||
|
||||
|
||||
def getSelectedPlacement(obj, sub):
|
||||
leaves = LCE.AllLeaves(obj.Shape)
|
||||
if sub == '':
|
||||
return 0 if len(leaves) == 1 else None
|
||||
subshape = obj.Shape.getElement(sub)
|
||||
getter = {
|
||||
'Vertex': (lambda sh: sh.Vertexes),
|
||||
'Edge': (lambda sh: sh.Edges),
|
||||
'Face': (lambda sh: sh.Faces)
|
||||
} [subshape.ShapeType]
|
||||
matches = []
|
||||
for index, leaf in enumerate(leaves):
|
||||
for it_sh in getter(leaf):
|
||||
if it_sh.isSame(subshape):
|
||||
matches.append(index)
|
||||
assert(len(matches) < 2)
|
||||
return matches[0]
|
||||
|
||||
# --------------------------------Gui commands----------------------------------
|
||||
|
||||
_library = {} #instances of TempoVis, per document
|
||||
_old_par = None #original value of DragAtCursor parameter
|
||||
_stack_len = 0 #how many times did we tried to modify the parameter
|
||||
|
||||
class CommandViewFromPlacement:
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : getIconPath("Lattice2_ViewFromPlacement.svg"),
|
||||
'MenuText': "View from placement",
|
||||
'Accel': "",
|
||||
'ToolTip': "View from placement. Places camera to where selected placement is. Click again to restore view.",
|
||||
'CmdType':"ForEdit"}
|
||||
|
||||
def Activated(self):
|
||||
import FreeCADGui as Gui
|
||||
|
||||
global _stack_len
|
||||
global _old_par
|
||||
|
||||
oldTV = _library.pop(App.ActiveDocument.Name, None)
|
||||
if oldTV is None:
|
||||
V = App.Vector
|
||||
sel = Gui.Selection.getSelectionEx()
|
||||
if len(sel) == 1 and len(sel[0].SubElementNames) < 2:
|
||||
#get placement
|
||||
index = getSelectedPlacement(sel[0].Object, sel[0].SubElementNames[0] if len(sel[0].SubElementNames) == 1 else '')
|
||||
plm = LBF.getPlacementsList(sel[0].Object)[index]
|
||||
OZ = plm.Rotation.multVec(V(0,0,1))
|
||||
OY = plm.Rotation.multVec(V(0,1,0))
|
||||
OX = plm.Rotation.multVec(V(1,0,0))
|
||||
print(OX)
|
||||
print(OZ)
|
||||
|
||||
#prepare
|
||||
tv = Show.TempoVis(App.ActiveDocument)
|
||||
tv.saveCamera()
|
||||
if SceneDetail is not None:
|
||||
tv.modify(SDParameter('User parameter:BaseApp/Preferences/View','DragAtCursor','Bool', False))
|
||||
else:
|
||||
dt = SDParameter('User parameter:BaseApp/Preferences/View','DragAtCursor','Bool', False)
|
||||
if _stack_len == 0:
|
||||
_old_par = dt.scene_value()
|
||||
_stack_len += 1
|
||||
dt.apply_data(dt.data)
|
||||
|
||||
#set up camera
|
||||
Gui.ActiveDocument.ActiveView.setCameraType('Perspective')
|
||||
from pivy import coin
|
||||
cam = Gui.ActiveDocument.ActiveView.getCameraNode()
|
||||
cam.position = tuple(plm.Base)
|
||||
rot = App.Rotation(V(), -OZ, -OX,'ZYX')
|
||||
cam.orientation = tuple(rot.Q)
|
||||
cam.heightAngle = -cam.heightAngle.getValue() #reversing height angle inverts the image. Using it in conjunction with upside-down camera to effectively reverse how view reacts to mouse.
|
||||
cam.focalDistance = 1e-5 #small focal distance makes camera spin about itself
|
||||
|
||||
#all done, remember.
|
||||
_library[App.ActiveDocument.Name] = tv
|
||||
else:
|
||||
infoMessage("Lattice2 View From Placement",
|
||||
"Lattice2 View From Placement command."
|
||||
"\n\nPlease select a placement, and invoke this tool. The camera will be placed there,"
|
||||
" and you'll be able to rotate around."
|
||||
"\n\nClick again to leave the mode.")
|
||||
else:
|
||||
oldTV.restore()
|
||||
if Gui.ActiveDocument.ActiveView.getCameraType() == 'Perspective':
|
||||
cam = Gui.ActiveDocument.ActiveView.getCameraNode()
|
||||
cam.heightAngle = abs(cam.heightAngle.getValue()) #workaround
|
||||
if SceneDetail is None:
|
||||
_stack_len -= 1
|
||||
if _stack_len == 0:
|
||||
dt = SDParameter('User parameter:BaseApp/Preferences/View','DragAtCursor','Bool', False)
|
||||
dt.apply_data(_old_par)
|
||||
|
||||
def IsActive(self):
|
||||
if Show is None: return False
|
||||
return hasattr(Gui.activeView(), 'getCameraNode')
|
||||
|
||||
if App.GuiUp:
|
||||
FreeCADGui.addCommand('Lattice2_ViewFromPlacement', CommandViewFromPlacement())
|
||||
|
||||
exportedCommands = [
|
||||
"Lattice2_ViewFromPlacement",
|
||||
]
|
File diff suppressed because one or more lines are too long
94
readme.md
Normal file
94
readme.md
Normal file
|
@ -0,0 +1,94 @@
|
|||
# What is Lattice2 workbench
|
||||
Lattice Workbench is a plug-in module (workbench) for FreeCAD.
|
||||
|
||||
The workbench purpose is working with placements and arrays of placements. It is a sort of assembly workbench, but with emphasis on arrays. There are no constraints and relations, there are just arrays of placements that can be generated, combined, transformed, superimposed and populated with shapes.
|
||||
|
||||
Ever wondered how to create a protractor with FreeCAD? That's the aim of the workbench (including tick labeling). Also, exploded assemblies can be made with the workbench.
|
||||
|
||||
Additionally, the workbench features a few general-purpose tools, such as parametric downgrade, bounding boxes, shape info tool, and tools for working with collections of shapes (compounds).
|
||||
|
||||
One of the big design goals of the workbench is being as parametric as possible.
|
||||
|
||||
# Getting started
|
||||
|
||||
Follow through [Basic Tutorial](https://github.com/DeepSOIC/Lattice2/wiki/Basic-Tutorial) to get the basic concept of Lattice2.
|
||||
|
||||
# Highlights
|
||||

|
||||
|
||||

|
||||
|
||||
Take a look at other examples in the [Gallery of screenshots](https://github.com/DeepSOIC/Lattice2/wiki/Gallery).
|
||||
|
||||
Let's have a glance over the most important capabilities that the workbench adds to FreeCAD:
|
||||
|
||||
* Re-use arrays as many times as you need. Unlike Draft array, which directly generates the array of shapes, lattice array tools generate arrays of placements. These can later be populated with shapes, as many times as necessary, without having to set up another array.
|
||||
|
||||
* Elements of array can be different. Unlike Draft Arrays, which always generate a set of equal shapes, Lattice arrays can be used to arrange a set of different shapes. Pack the shapes to be arranged into a Compound, and use Lattice [Populate with children](https://github.com/DeepSOIC/Lattice2/wiki/Feature-PopulateChildren) feature to arrange them.
|
||||
|
||||
* Arrays of placements can be combined, inverted, generated from existing shape arrangements, made from individual placements, projected onto shapes, filtered, etc. This allows to produce complex arrangements without scripting.
|
||||
|
||||
* single placements can be used for primitive assembling of parts.
|
||||
|
||||
* linear arrays and polar arrays can have their axes linked to edges of shapes
|
||||
|
||||
* parametric explode commands allow extraction of specific elements of arrays, without losing parametric relation to the original.
|
||||
|
||||
* [ParaSeries](https://github.com/DeepSOIC/Lattice2/wiki/Feature-ParaSeries) feature allows to generate a series of parts with some parameter varied over a list of values.
|
||||
|
||||
# Why Lattice2, not just Lattice?
|
||||
Lattice2 was created at the moment when breaking changes needed to be made, but there were a few things made with Lattice. So, it was decided to keep the workbench in that time's state indefinitely as version 1.0, and start development of a new version.
|
||||
|
||||
The goal was to be able to have both Lattice v1 and v2 in a single FreeCAD installation. So a new repository was started, and all the files were renamed to start with 'lattice2' or otherwise differ from those of Lattice v1.
|
||||
|
||||
# What's changed in Lattice2
|
||||
|
||||
* Population tools now have 'move' mode: a placement/set of placements can be supplied to treat as origins of the objects being populated
|
||||
|
||||
* Experimental recompute controlling tools were added
|
||||
|
||||
* Most icons were redesigned to follow a concept
|
||||
|
||||
* Lattice workbench can now be imported from Py console all at once, like that: `import Lattice2`
|
||||
|
||||
* ParaSeries feature was added, which can create a series of parts by changing some parameter of the model.
|
||||
|
||||
# Download/install
|
||||
repository: https://github.com/DeepSOIC/Lattice2
|
||||
|
||||
Lattice2 WB requires FreeCAD no less than v0.16.5155.
|
||||
|
||||
The workbench is OS independent, it should work on any system FreeCAD can be run on. If you find that it doesn't - that is a bug. Please make an issue.
|
||||
|
||||
Lattice2 is written in FreeCAD's Python, and must be run from within FreeCAD. It requires no compilation, and can be installed by copying the repository to a special location.
|
||||
|
||||
# Manual install:
|
||||
1. Scroll to the top of the page, and click 'download zip' button
|
||||
|
||||
2. Unpack the contents into a "Lattice2" folder created in \Path\to\FreeCAD\Mod, and restart FreeCAD. <br>
|
||||
Note that InitGui.py (and the rest of .py files) should end up directly under Mod\Lattice2 (not under nested directory like Mod\Lattice2\Lattice2).
|
||||
|
||||
After you install the workbench, it should appear at the bottom of list of workbench selector in FreeCAD.
|
||||
|
||||
# Automated installation:
|
||||
* Lattice2 workbench is packaged to Launchpad in the Ubuntu FreeCAD Community PPA (thanks to @abdullahtahiriyo).
|
||||
* Lattice2 can be installed via [FreeCAD addons installer macro](https://github.com/FreeCAD/FreeCAD-addons)
|
||||
* Lattice2 can be installed via @microelly's [Plugin Loader](https://github.com/microelly2/freecad-pluginloader)
|
||||
|
||||
|
||||
# License
|
||||
Lattice workbench is licenced under LGPL V2, just like FreeCAD. For more info, see copying.lib file in the repository.
|
||||
|
||||
# Getting Help
|
||||
|
||||
Documentation: see [Lattice2 wiki](https://github.com/DeepSOIC/Lattice2/wiki) on Github. As the word "wiki" suggests, you can help by editing the documentation.
|
||||
|
||||
If you need help on something specific, you can ask a question on [FreeCAD forum](http://forum.freecadweb.org/index.php) (there is no Lattice forum yet...). You can also ask me directly.
|
||||
|
||||
If you have found a bug, report it [here, in Github's issue tracker for Lattice2](https://github.com/DeepSOIC/Lattice2/issues). You can also post ideas for new features there, as well as plain questions.
|
||||
|
||||
If you have fixed a bug, or implemented a new feature you think suits the workbench, or whatever - feel free to make a pull-request here on github.
|
||||
|
||||
# Status
|
||||
This version can be considered a release candidate. I will take care to not make breaking changes, but new functionality may keep coming.
|
||||
|
BIN
shapes/paperplane-orimarker-refplm.FCStd
Normal file
BIN
shapes/paperplane-orimarker-refplm.FCStd
Normal file
Binary file not shown.
149
shapes/paperplane-orimarker-refplm.iv
Normal file
149
shapes/paperplane-orimarker-refplm.iv
Normal 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
|
||||
}
|
BIN
shapes/tetra-orimarker-refplm.FCStd
Normal file
BIN
shapes/tetra-orimarker-refplm.FCStd
Normal file
Binary file not shown.
160
shapes/tetra-orimarker-refplm.iv
Normal file
160
shapes/tetra-orimarker-refplm.iv
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user