Rich's Seed Eco-Home Design Software

From Open Source Ecology
Revision as of 21:32, 7 January 2026 by Rich A. (talk | contribs) (SUPER ALIGN!)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

SUPER ALIGN!

I had AI make for me an alignment tool in FreeCAD 1.0 so that it can align a folder of objects with objects, or other folder of objects, so compound objects don't have to be created. Compound objects prevent the editing of component objects that are baked in. Super Align allows for the alignment of folders without creating these compounds.

Instructions:

Run Macro:

-Click Macro > 📝 Macros...
-Copy and Paste the code below in the macro window
-Highlight all the code
-Click Macro > Execute Macro

A window with a red button that says Align! should appear

-Click on the 3D view tab below to get pack to your project.

The Align! window should be there. You can minimize it and dock it to other windows.

-Click a point, edge, or face on your movable object
-On Mac command Click a point, edge, or face on your fixed object
-Click Align!

Macro Code: import FreeCAD as App import FreeCADGui as Gui from PySide import QtGui, QtCore

def get_parent_container(obj):

   """Find container (Part/Group) one level up, or return obj itself."""
   for container in App.ActiveDocument.Objects:
       if hasattr(container, 'Group') and obj in container.Group:
           return container
   return obj

def super_align():

   sel_ex = Gui.Selection.getSelectionEx()
   if len(sel_ex) != 2:
       print("❌ Ctrl+click point/edge/face on MOVABLE, then FIXED")
       return
   
   # Store visibility states
   original_vis = {}
   for obj in App.ActiveDocument.Objects:
       if hasattr(obj, 'Visibility'):
           original_vis[obj.Name] = obj.Visibility
   
   # Get parents (container or object itself)
   movable_parent = get_parent_container(sel_ex[0].Object)
   fixed_parent = get_parent_container(sel_ex[1].Object)
   
   print(f"MOVABLE: '{movable_parent.Label}' → FIXED: '{fixed_parent.Label}'")
   
   # Get movable objects (whole container or single)
   if hasattr(movable_parent, 'Group') and movable_parent.Group:
       movable_objects = list(movable_parent.Group)
   else:
       movable_objects = [movable_parent]
   
   # Get subelement positions
   def get_sub_pos(sub_ex):
       sub_obj = sub_ex.SubObjects[0]
       if hasattr(sub_obj, 'Point'):
           return sub_obj.Point
       elif hasattr(sub_obj, 'CenterOfMass'):
           return sub_obj.CenterOfMass
       else:
           # Bounding box center
           bb = sub_obj.BoundBox
           return App.Vector((bb.XMin+bb.XMax)/2, (bb.YMin+bb.YMax)/2, (bb.ZMin+bb.ZMax)/2)
   
   movable_pos = get_sub_pos(sel_ex[0])
   fixed_pos = get_sub_pos(sel_ex[1])
   offset = fixed_pos - movable_pos
   
   print(f"📐 Incremental offset: {offset.x:.1f}, {offset.y:.1f}, {offset.z:.1f}")
   
   # INCREMENTAL ALIGNMENT (preserves relative positions)
   aligned_count = 0
   for obj in movable_objects:
       if hasattr(obj, 'Placement'):
           new_base = obj.Placement.Base + offset
           obj.Placement = App.Placement(new_base, obj.Placement.Rotation)
           aligned_count += 1
   
   # Restore visibility
   for name, vis in original_vis.items():
       obj = App.ActiveDocument.getObject(name)
       if obj and hasattr(obj, 'Visibility'):
           obj.Visibility = vis
   
   Gui.Selection.clearSelection()
   Gui.Selection.addSelection(movable_parent)
   print(f"✅ INCREMENTALLY aligned {aligned_count} objects!")
  1. CREATE REFINED DOCKED PANEL

mw = Gui.getMainWindow() dock = QtGui.QDockWidget("Super Align", mw) dock.setObjectName("SuperAlignDock") dock.setFeatures(QtGui.QDockWidget.DockWidgetMovable |

               QtGui.QDockWidget.DockWidgetFloatable | 
               QtGui.QDockWidget.DockWidgetClosable)

widget = QtGui.QWidget() layout = QtGui.QVBoxLayout(widget)

  1. BIGGER TITLE

title = QtGui.QLabel("Super Align") title.setStyleSheet("font-weight: bold; font-size: 20px; color: #2E8B57; padding: 5px;") layout.addWidget(title)

  1. INSTRUCTIONS (small text under title)

instructions = QtGui.QLabel(""" • Select point/edge/face on movable object • Select point/edge/face on fixed object • Click Align! """) instructions.setStyleSheet("font-size: 10px; color: #666; padding: 2px; margin: 0px;") instructions.setWordWrap(True) layout.addWidget(instructions)

  1. THINNER ALIGN BUTTON

align_btn = QtGui.QPushButton("Align!") align_btn.setToolTip("Ctrl-click movable point/edge/face → Ctrl-click fixed → Align!") align_btn.clicked.connect(super_align) align_btn.setStyleSheet("""

   QPushButton { 
       font-weight: bold; 
       min-height: 25px; 
       max-height: 25px; 
       background-color: #FF6B6B; 
       border-radius: 5px;
   }

""") layout.addWidget(align_btn)

widget.setLayout(layout) dock.setWidget(widget) mw.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) dock.show()

print("✅ Super Align REFINED panel ready!")