~freecad-community/freecad-extras/lattice2

227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
1
#***************************************************************************
2
#*                                                                         *
3
#*   Copyright (c) 2016 - Victor Titov (DeepSOIC)                          *
4
#*                                               <vv.titov@gmail.com>      *  
5
#*                                                                         *
6
#*   This program is free software; you can redistribute it and/or modify  *
7
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
8
#*   as published by the Free Software Foundation; either version 2 of     *
9
#*   the License, or (at your option) any later version.                   *
10
#*   for detail see the LICENCE text file.                                 *
11
#*                                                                         *
12
#*   This program is distributed in the hope that it will be useful,       *
13
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15
#*   GNU Library General Public License for more details.                  *
16
#*                                                                         *
17
#*   You should have received a copy of the GNU Library General Public     *
18
#*   License along with this program; if not, write to the Free Software   *
19
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
20
#*   USA                                                                   *
21
#*                                                                         *
22
#***************************************************************************
23
24
__title__="ShapeCopy module for Lattice2"
25
__author__ = "DeepSOIC"
26
__url__ = ""
27
__doc__ = "Utility methods to copy shapes"
28
29
import FreeCAD
233 by DeepSOIC
SubLink: Fix #8 : incorrect position of Vertex
30
import Part
279 by DeepSOIC
New feature: PartDesign Pattern!
31
from lattice2GeomUtils import PlacementsFuzzyCompare
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
32
33
def shallowCopy(shape, extra_placement = None):
34
    """shallowCopy(shape, extra_placement = None): creates a shallow copy of a shape. The 
279 by DeepSOIC
New feature: PartDesign Pattern!
35
    copy will match by isSame/isEqual/isPartner tests, but will have an independent placement.
36
    Supports matrix, but the matrix should be pure placement (not be mirroring)."""
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
37
    
38
    copiers = {
248 by DeepSOIC
Py3: fix syntax errors
39
      "Vertex": lambda sh: sh.Vertexes[0],
40
      "Edge": lambda sh: sh.Edges[0],
41
      "Wire": lambda sh: sh.Wires[0],
42
      "Face": lambda sh: sh.Faces[0],
43
      "Shell": lambda sh: sh.Shells[0],
44
      "Solid": lambda sh: sh.Solids[0],
45
      "CompSolid": lambda sh: sh.CompSolids[0],
46
      "Compound": lambda sh: sh.Compounds[0],
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
47
      }
48
    copier = copiers.get(shape.ShapeType)
49
    if copier is None:
248 by DeepSOIC
Py3: fix syntax errors
50
        copier = lambda sh: sh.copy()
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
51
        FreeCAD.Console.PrintWarning("Lattice2: shallowCopy: unexpected shape type '{typ}'. Using deep copy instead.\n".format(typ= shape.ShapeType))
52
    ret = copier(shape)
53
    if extra_placement is not None:
262 by DeepSOIC
ShapeCopy: add support for mirroring
54
        if hasattr(extra_placement, 'toMatrix'):
55
            ret.Placement = extra_placement.multiply(ret.Placement)
56
        elif extra_placement.determinant() - 1.0 < 1e-7:
57
            ret.transformShape(extra_placement)
58
        else:
59
            raise NonPlacementMatrixError("Matrix supplied to shallowCopy must be unitary.")
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
60
    return ret
61
    
62
def deepCopy(shape, extra_placement = None):
63
    """deepCopy(shape, extra_placement = None): Copies all subshapes. The copy will not match by isSame/isEqual/
279 by DeepSOIC
New feature: PartDesign Pattern!
64
    isPartner tests. If matrix is provided, redirects the call to transformCopy."""
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
65
    
66
    if extra_placement is not None:
262 by DeepSOIC
ShapeCopy: add support for mirroring
67
        if hasattr(extra_placement, 'toMatrix'):
68
            ret = shape.copy()
69
            ret.Placement = extra_placement.multiply(ret.Placement)
70
        else:
71
            ret = shallowCopy(shape)
72
            ret.transformShape(extra_placement, True)
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
73
    return ret    
74
    
75
def transformCopy(shape, extra_placement = None):
76
    """transformCopy(shape, extra_placement = None): creates a deep copy shape with shape's placement applied to 
279 by DeepSOIC
New feature: PartDesign Pattern!
77
    the subelements (the placement of returned shape is zero). Supports matrices, including mirroring matrices."""
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
78
    
79
    if extra_placement is None:
80
        extra_placement = FreeCAD.Placement()
262 by DeepSOIC
ShapeCopy: add support for mirroring
81
    if hasattr(extra_placement, 'toMatrix'):
82
        extra_placement = extra_placement.toMatrix()
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
83
    ret = shape.copy()
233 by DeepSOIC
SubLink: Fix #8 : incorrect position of Vertex
84
    if ret.ShapeType == "Vertex":
85
        # oddly, on Vertex, transformShape behaves strangely. So we'll create a new vertex instead.
262 by DeepSOIC
ShapeCopy: add support for mirroring
86
        ret = Part.Vertex(extra_placement.multiply(ret.Point))
233 by DeepSOIC
SubLink: Fix #8 : incorrect position of Vertex
87
    else:
262 by DeepSOIC
ShapeCopy: add support for mirroring
88
        splm = ret.Matrix
89
        ret.Matrix = FreeCAD.Base.Matrix()
90
        ret.transformShape(extra_placement.multiply(splm), True)
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
91
    return ret
92
279 by DeepSOIC
New feature: PartDesign Pattern!
93
def transformCopy_Smart(shape, feature_placement):
94
    """transformCopy_Smart(shape, feature_placement): gets rid of shape's internal placement 
95
    (by applying transform to all its elements), and assigns feature_placement to the placement. 
96
    I.e. feature_placement is the additional transform to apply. Unlike transformCopy, creates 
97
    a shallow copy if possible. Does not support matrices."""
98
    
99
    if shape.isNull():
100
        return shape
101
    if PlacementsFuzzyCompare(shape.Placement, FreeCAD.Placement()):
102
        sh = shallowCopy(shape)
103
    else:
104
        sh = transformCopy(shape)
105
    sh.Placement = feature_placement
106
    return sh
107
227.1.2 by DeepSOIC
Populate: add property to control shallow/deep copy
108
    
109
copy_types = ["Shallow copy", "Deep copy", "Transformed deep copy"]
110
copy_functions = [shallowCopy, deepCopy, transformCopy]
111
112
def getCopyTypeIndex(copy_type_string):
113
    return copy_types.index(str(copy_type_string))
114
115
def copyShape(shape, copy_type_index, extra_placement = None):
116
    """copyShape(shape, copy_type_index, extra_placement = None): copies a shape (or creates 
117
    a moved copy of shape, if extra_placement is given). copy_type_index should be obtained 
118
    from string by getCopyTypeIndex() function."""
119
    
120
    global copy_functions
121
    return copy_functions[copy_type_index](shape, extra_placement)    
262 by DeepSOIC
ShapeCopy: add support for mirroring
122
123
def transformShape(shape, extra_placement):
124
    """transformShape(shape, extra_placement): returns shape with  extra_placement applied to it.
125
    extra_placement must be either a Placement, or a Matrix. Matrix can be mirroring.
126
    shallowCopy is done if Placement or a placement matrix. transformCopy is done if the matrix features mirroring."""
127
128
    if hasattr(extra_placement, 'toMatrix'):
129
        # extra_placement is a Placement
130
        return shallowCopy(shape, extra_placement)
131
    else:
132
        # extra_placement is a Matrix
133
        return transformCopy(shape, extra_placement)
134
    
135
136
class NonPlacementMatrixError(ValueError):
137
    pass