~freecad-community/freecad-extras/lattice2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2016 - 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__="ShapeCopy module for Lattice2"
__author__ = "DeepSOIC"
__url__ = ""
__doc__ = "Utility methods to copy shapes"

import FreeCAD
import Part
from lattice2GeomUtils import PlacementsFuzzyCompare

def shallowCopy(shape, extra_placement = None):
    """shallowCopy(shape, extra_placement = None): creates a shallow copy of a shape. The 
    copy will match by isSame/isEqual/isPartner tests, but will have an independent placement.
    Supports matrix, but the matrix should be pure placement (not be mirroring)."""
    
    copiers = {
      "Vertex": lambda sh: sh.Vertexes[0],
      "Edge": lambda sh: sh.Edges[0],
      "Wire": lambda sh: sh.Wires[0],
      "Face": lambda sh: sh.Faces[0],
      "Shell": lambda sh: sh.Shells[0],
      "Solid": lambda sh: sh.Solids[0],
      "CompSolid": lambda sh: sh.CompSolids[0],
      "Compound": lambda sh: sh.Compounds[0],
      }
    copier = copiers.get(shape.ShapeType)
    if copier is None:
        copier = lambda sh: sh.copy()
        FreeCAD.Console.PrintWarning("Lattice2: shallowCopy: unexpected shape type '{typ}'. Using deep copy instead.\n".format(typ= shape.ShapeType))
    ret = copier(shape)
    if extra_placement is not None:
        if hasattr(extra_placement, 'toMatrix'):
            ret.Placement = extra_placement.multiply(ret.Placement)
        elif extra_placement.determinant() - 1.0 < 1e-7:
            ret.transformShape(extra_placement)
        else:
            raise NonPlacementMatrixError("Matrix supplied to shallowCopy must be unitary.")
    return ret
    
def deepCopy(shape, extra_placement = None):
    """deepCopy(shape, extra_placement = None): Copies all subshapes. The copy will not match by isSame/isEqual/
    isPartner tests. If matrix is provided, redirects the call to transformCopy."""
    
    if extra_placement is not None:
        if hasattr(extra_placement, 'toMatrix'):
            ret = shape.copy()
            ret.Placement = extra_placement.multiply(ret.Placement)
        else:
            ret = shallowCopy(shape)
            ret.transformShape(extra_placement, True)
    return ret    
    
def transformCopy(shape, extra_placement = None):
    """transformCopy(shape, extra_placement = None): creates a deep copy shape with shape's placement applied to 
    the subelements (the placement of returned shape is zero). Supports matrices, including mirroring matrices."""
    
    if extra_placement is None:
        extra_placement = FreeCAD.Placement()
    if hasattr(extra_placement, 'toMatrix'):
        extra_placement = extra_placement.toMatrix()
    ret = shape.copy()
    if ret.ShapeType == "Vertex":
        # oddly, on Vertex, transformShape behaves strangely. So we'll create a new vertex instead.
        ret = Part.Vertex(extra_placement.multiply(ret.Point))
    else:
        splm = ret.Matrix
        ret.Matrix = FreeCAD.Base.Matrix()
        ret.transformShape(extra_placement.multiply(splm), True)
    return ret

def transformCopy_Smart(shape, feature_placement):
    """transformCopy_Smart(shape, feature_placement): gets rid of shape's internal placement 
    (by applying transform to all its elements), and assigns feature_placement to the placement. 
    I.e. feature_placement is the additional transform to apply. Unlike transformCopy, creates 
    a shallow copy if possible. Does not support matrices."""
    
    if shape.isNull():
        return shape
    if PlacementsFuzzyCompare(shape.Placement, FreeCAD.Placement()):
        sh = shallowCopy(shape)
    else:
        sh = transformCopy(shape)
    sh.Placement = feature_placement
    return sh

    
copy_types = ["Shallow copy", "Deep copy", "Transformed deep copy"]
copy_functions = [shallowCopy, deepCopy, transformCopy]

def getCopyTypeIndex(copy_type_string):
    return copy_types.index(str(copy_type_string))

def copyShape(shape, copy_type_index, extra_placement = None):
    """copyShape(shape, copy_type_index, extra_placement = None): copies a shape (or creates 
    a moved copy of shape, if extra_placement is given). copy_type_index should be obtained 
    from string by getCopyTypeIndex() function."""
    
    global copy_functions
    return copy_functions[copy_type_index](shape, extra_placement)    

def transformShape(shape, extra_placement):
    """transformShape(shape, extra_placement): returns shape with  extra_placement applied to it.
    extra_placement must be either a Placement, or a Matrix. Matrix can be mirroring.
    shallowCopy is done if Placement or a placement matrix. transformCopy is done if the matrix features mirroring."""

    if hasattr(extra_placement, 'toMatrix'):
        # extra_placement is a Placement
        return shallowCopy(shape, extra_placement)
    else:
        # extra_placement is a Matrix
        return transformCopy(shape, extra_placement)
    

class NonPlacementMatrixError(ValueError):
    pass