# -*- coding: utf-8 -*- from __future__ import unicode_literals __Name__ = 'Highlight Common parts' __Comment__ = 'Compute the common parts between selected shapes' __Author__ = 'JMG, galou and other contributors' __Version__ = '2.3.2' __Date__ = '2021-07-01' __License__ = 'CC0-1.0' __Web__ = 'https://freecadweb.org/wiki/Macro_HighlightCommon' __Wiki__ = 'https://freecadweb.org/wiki/Macro_HighlightCommon' __Icon__ = 'HighlightCommon.png' __Help__ = 'Select at least two objects and run' __Status__ = 'Production' __Requires__ = 'FreeCAD V0.17+' __Communication__ = 'https://github.com/FreeCAD/FreeCAD-macros/issues/' __Files__ = 'HighlightCommon.png' from PySide.QtGui import QMessageBox # FreeCAD's special PySide! import FreeCAD as app import FreeCADGui as gui PREFERENCE_PATH = 'User parameter:BaseApp/Preferences/Mod/HighlightCommon' def load_and_save_settings(): param_change = 'change_transparency' param_transparency = 'transparency' p = app.ParamGet(PREFERENCE_PATH) change_transparency = p.GetBool(param_change, True) transparency = p.GetInt(param_transparency, 80) p.SetBool(param_change, change_transparency) p.SetInt(param_transparency, transparency) return change_transparency, transparency def main(): # Store active doc in case it may change during run. doc = app.activeDocument() if doc is None: return change_transparency, transparency = load_and_save_settings() colli_grp = None # Group object to group collisions. colli_max = 0 # Maximum collision volume. # Open a transaction in undo pile. doc.openTransaction('Seeking collisions') objectsToEnumerate = gui.Selection.getSelection() if len(objectsToEnumerate) < 2: objectsToEnumerate = doc.Objects # Ensure list of unique objects. object_list = [] for obj in objectsToEnumerate: if ((obj not in object_list) and hasattr(obj, 'Shape') and hasattr(obj, 'getGlobalPlacement') and hasattr(obj, 'Label')): object_list.append(obj) # Going through selected objects (object A). for i, object_a in enumerate(object_list): shape_a = object_a.Shape.copy() shape_a.Placement = object_a.getGlobalPlacement() label_a = object_a.Label # Making selected objects transparent. if change_transparency: try: object_a.ViewObject.Transparency = transparency except AttributeError: pass # Comparing object A with all # following ones in the list (object B). for object_b in object_list[(i + 1):]: shape_b = object_b.Shape.copy() shape_b.Placement = object_b.getGlobalPlacement() label_b = object_b.Label common = shape_a.common(shape_b) # Making selected objects transparent. if change_transparency: try: object_b.ViewObject.Transparency = transparency except AttributeError: pass # If object A & object B have a collision # display a message with collision volume and # add a new representative shape in the group. if common.Volume > 1e-6: app.Console.PrintMessage( 'Volume of the intersection between {} and {}: {:.3f} mm³\n'.format( label_a, label_b, common.Volume)) colli_max = common.Volume if common.Volume > colli_max else colli_max if not colli_grp: # Create group if it doesn't already exist. colli_grp = doc.addObject('App::DocumentObjectGroup', 'Collisions') intersection_object = doc.addObject( 'Part::Feature') intersection_object.Label = '{} - {}'.format( label_a, label_b) intersection_object.Shape = common intersection_object.ViewObject.ShapeColor = (1.0, 0.0, 0.0, 1.0) colli_grp.addObject(intersection_object) else: # If no collision, just inform the user. app.Console.PrintMessage( 'No intersection between {} and {}\n'.format( label_a, label_b)) # If collisions have been found, commit the undo transaction and # give a summary (count + max value) to the user. if colli_grp: doc.commitTransaction() app.Console.PrintMessage( '{} collision(s) found between selected objects\nMaximum collision: {:.3f} mm³\n'.format( len(colli_grp.Group), colli_max)) doc.recompute() else: # If no collision has been found, just inform the user about it. doc.abortTransaction() if len(object_list) == 2: app.Console.PrintWarning('No collision found between selected objects\n') else: app.Console.PrintWarning('No suitable objects selected, select at least two objects\n') if __name__ == '__main__': main()