def applyFeature(baseshape, feature, transforms, mts): if hasattr(feature, 'Proxy') and hasattr(feature.Proxy, 'applyTransformed'): return feature.Proxy.applyTransformed(feature, baseshape, transforms, mts) task = getFeatureShapes(feature) for sign, featureshape in task: actionshapes = [] for transform in transforms: actionshapes.append(shallowCopy(featureshape, transform)) 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 for actionshape in actionshapes: assert (sign != 0) realsign = sign * mts.sign_override if abs(mts.sign_override) == +2: realsign = int(mts.sign_override / 2) if realsign > 0: baseshape = baseshape.fuse(actionshape) elif realsign < 0: baseshape = baseshape.cut(actionshape) if baseshape.isNull(): raise FeatureFailure( 'applying {name} failed - returned shape is null'.format( name=feature.Name)) return baseshape
def getFeatureShapes(feature): sign = feature_sign(feature, raise_if_unsupported=True) if hasattr(feature, 'AddSubShape'): sh = shallowCopy(feature.AddSubShape) sh.Placement = feature.Placement return [(sign, sh)] elif feature.isDerivedFrom('PartDesign::Boolean'): return [(sign, obj.Shape) for obj in feature.Group] else: raise FeatureUnsupportedError( "Feature {name} is not supported.".format(name=feature.Name))
def execute(self, obj): # please, don't override. Override derivedExecute instead. plms = self.derivedExecute(obj) if plms is not None: if plms == "suppress": return obj.NumElements = len(plms) shapes = [] markerSize = obj.MarkerSize if markerSize < DistConfusion: markerSize = getMarkerSizeEstimate(plms) marker = lattice2Markers.getPlacementMarker(scale=markerSize, markerID=obj.MarkerShape) bExposing = False if obj.ExposePlacement: if len(plms) == 1: bExposing = True else: lattice2Executer.warning( obj, "Multiple placements are being fed, can't expose placements. Placement property will be forced to zero.", ) obj.Placement = App.Placement() if bExposing: obj.Shape = shallowCopy(marker) obj.Placement = plms[0] else: for plm in plms: sh = shallowCopy(marker) sh.Placement = plm shapes.append(sh) if len(shapes) == 0: obj.Shape = lattice2Markers.getNullShapeShape(markerSize) raise ValueError("Lattice object is null") sh = Part.makeCompound(shapes) obj.Shape = sh if obj.isLattice == "Auto-Off": obj.isLattice = "Auto-On" else: # DerivedExecute didn't return anything. Thus we assume it # has assigned the shape, and thus we don't do anything. # Moreover, we assume that it is no longer a lattice object, so: if obj.isLattice == "Auto-On": obj.isLattice = "Auto-Off" if obj.ExposePlacement: if obj.Shape.ShapeType == "Compound": children = obj.Shape.childShapes() if len(children) == 1: obj.Placement = children[0].Placement obj.Shape = children[0] else: obj.Placement = App.Placement() else: # nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized. pass return
def execute(self, obj): # please, don't override. Override derivedExecute instead. plms = self.derivedExecute(obj) if plms is not None: if plms == "suppress": return obj.NumElements = len(plms) shapes = [] markerSize = obj.MarkerSize if markerSize < DistConfusion: markerSize = getMarkerSizeEstimate(plms, obj) marker = lattice2Markers.getPlacementMarker( scale=markerSize, markerID=obj.MarkerShape) bExposing = False if obj.ExposePlacement: if len(plms) == 1: bExposing = True else: lattice2Executer.warning( obj, "Multiple placements are being fed, can't expose placements. Placement property will be forced to zero." ) obj.Placement = App.Placement() if bExposing: obj.Shape = shallowCopy(marker) obj.Placement = plms[0] else: for plm in plms: sh = shallowCopy(marker) sh.Placement = plm shapes.append(sh) if len(shapes) == 0: obj.Shape = lattice2Markers.getNullShapeShape(markerSize) raise ValueError('Lattice object is null') sh = Part.makeCompound(shapes) sh.Placement = obj.Placement obj.Shape = sh if obj.isLattice == 'Auto-Off': obj.isLattice = 'Auto-On' else: # DerivedExecute didn't return anything. Thus we assume it # has assigned the shape, and thus we don't do anything. # Moreover, we assume that it is no longer a lattice object, so: if obj.isLattice == 'Auto-On': obj.isLattice = 'Auto-Off' if obj.ExposePlacement: if obj.Shape.ShapeType == "Compound": children = obj.Shape.childShapes() if len(children) == 1: obj.Placement = children[0].Placement obj.Shape = children[0] else: obj.Placement = App.Placement() else: #nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized. pass return
def execute(self, obj): base = screen(obj.ShapeLink).Shape if obj.CompoundTraversal == "Use as a whole": baseChildren = [base] else: if base.ShapeType != 'Compound': base = Part.makeCompound([base]) if obj.CompoundTraversal == "Recursive": baseChildren = LCE.AllLeaves(base) else: baseChildren = base.childShapes() N = len(baseChildren) orients = [] if obj.OrientMode == "global": orients = [App.Placement()] * N elif obj.OrientMode == "local of compound": orients = [screen(obj.ShapeLink).Placement] * N elif obj.OrientMode == "local of child": orients = [child.Placement for child in baseChildren] elif obj.OrientMode == "use OrientLink": orients = LBF.getPlacementsList(screen(obj.OrientLink), context=obj) if len(orients) == N: pass elif len(orients) > N: Executer.warning( obj, "Array of placements linked in OrientLink has more placements (" + str(len(orients)) + ") than bounding boxes to be constructed (" + str(len(baseChildren)) + "). Extra placements will be dropped.") elif len(orients) == 1: orients = [orients[0]] * N else: raise ValueError( obj.Name + ": Array of placements linked in OrientLink has not enough placements (" + str(len(orients)) + ") than bounding boxes to be constructed (" + str(len(baseChildren)) + ").") else: raise ValueError(obj.Name + ": OrientMode " + obj.OrientMode + " not implemented =(") # mark placements with no rotation for i in range(N): Q = orients[i].Rotation.Q # Quaternions for zero rotation are either (0,0,0,1) or (0,0,0,-1). For non-zero # 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. if abs(Q[0]) + abs(Q[1]) + abs(Q[2]) < ParaConfusion: orients[i] = None from lattice2ShapeCopy import shallowCopy boxes_shapes = [] for i in range(N): child = baseChildren[i] if orients[i] is not None: child = shallowCopy(child) child.Placement = orients[i].inverse().multiply( child.Placement) if obj.Precision: bb = getPrecisionBoundBox(child) else: bb = child.BoundBox bb = scaledBoundBox(bb, obj.ScaleFactor) bb.enlarge(obj.Padding) bb_shape = boundBox2RealBox(bb) if orients[i] is not None: bb_shape.transformShape(orients[i].toMatrix(), True) boxes_shapes.append(bb_shape) #Fill in read-only properties if N == 1: obj.Size = App.Vector(bb.XLength, bb.YLength, bb.ZLength) cnt = bb.Center if orients[0] is not None: cnt = orients[0].multVec(cnt) obj.Center = cnt else: obj.Size = App.Vector() obj.Center = App.Vector() if obj.CompoundTraversal == "Use as a whole": assert (N == 1) obj.Shape = boxes_shapes[0] else: obj.Shape = Part.makeCompound(boxes_shapes)