From a50ad1f96ae1f62011a79c949441d3b0fd02527a Mon Sep 17 00:00:00 2001
From: mehtank <mehtank@ucla.edu>
Date: Fri, 9 Sep 2022 06:11:11 +0000
Subject: [PATCH] Fix / extend interface connections especially wrt face-face
 connections also fix bug in numsym: Return the rows of an array/matrix as an
 iterable, not just the number of rows

---
 rocolib/api/components/Component.py    | 4 ++--
 rocolib/api/composables/graph/Face.py  | 5 ++++-
 rocolib/api/composables/graph/Graph.py | 7 ++++---
 rocolib/api/ports/FacePort.py          | 8 +++++++-
 rocolib/utils/numsym.py                | 5 +----
 5 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/rocolib/api/components/Component.py b/rocolib/api/components/Component.py
index 8e81033..e7c50ee 100644
--- a/rocolib/api/components/Component.py
+++ b/rocolib/api/components/Component.py
@@ -273,10 +273,10 @@ class Component(Parameterized):
 
         fromPort = self.getInterfaces(*fromInterface)
         toPort = self.getInterfaces(*toInterface)
-        if fromPort.canMate(toPort):
+        if fromPort.canMate(toPort) or toPort.canMate(fromPort):
             self.connections.setdefault(name, [fromInterface, toInterface, kwargs])
         else:
-            raise AttributeError(f"{fromInterface} cannot connect to {toInterface} according to getMate")
+            raise AttributeError(f"{fromInterface} ({fromPort} : {type(fromPort)}) cannot connect to {toInterface} ({toPort} : {type(toPort)}) according to getMate")
 
     def delConnection(self, name):
       self.connections.pop(name)
diff --git a/rocolib/api/composables/graph/Face.py b/rocolib/api/composables/graph/Face.py
index aaaad36..2f57407 100644
--- a/rocolib/api/composables/graph/Face.py
+++ b/rocolib/api/composables/graph/Face.py
@@ -220,8 +220,11 @@ class Face(object):
   def addDecoration(self, pts):
     self.decorations.append(pts)
 
-  def addFace(self, face, transform):
+  def addFace(self, face, transform, copyDecorations=False):
     self.joinedFaces.append((face, transform))
+    if copyDecorations:
+      for d in self.decorations:
+        face.addDecoration(d)
 
   def preTransform(self, edge):
     index = self.edges.index(edge)
diff --git a/rocolib/api/composables/graph/Graph.py b/rocolib/api/composables/graph/Graph.py
index 17f4dc4..f39c281 100644
--- a/rocolib/api/composables/graph/Graph.py
+++ b/rocolib/api/composables/graph/Graph.py
@@ -107,13 +107,14 @@ class Graph():
     self.addFace(toFace, prefix)
     self.mergeFace(fromFace, toFace.name, transform)
 
-  def mergeFace(self, fromFaceName, toFaceName, transform=None):
+  def mergeFace(self, fromFaceName, toFaceName, transform=None, offset=(0,0), copyDecorations=False):
     fromFace = self.getFace(fromFaceName)
     toFace = self.getFace(toFaceName)
+    toFace.transform(origin=offset)
     if transform is None:
         transform = np.eye(4)
-    fromFace.addFace(toFace, transform)
-    toFace.addFace(fromFace, np.inv(transform))
+    fromFace.addFace(toFace, transform, copyDecorations)
+    toFace.addFace(fromFace, np.inv(transform), copyDecorations)
 
   def attachEdge(self, fromEdge, newFace, newEdge, prefix=None, root=False, angle=0, edgeType=None, joints=None):
     # XXX should set angle from a face, not absolute angle of the face
diff --git a/rocolib/api/ports/FacePort.py b/rocolib/api/ports/FacePort.py
index 3b3a162..9bfa32a 100644
--- a/rocolib/api/ports/FacePort.py
+++ b/rocolib/api/ports/FacePort.py
@@ -1,5 +1,7 @@
 from rocolib.api.ports import Port
 from rocolib.utils.utils import prefix as prefixString
+from rocolib.utils.numsym import deg2rad
+from rocolib.utils.transforms import RotateX
 
 class FacePort(Port):
   def __init__(self, parent, graph, face):
@@ -36,4 +38,8 @@ class FacePort(Port):
     if isinstance(toPort, FacePort):
       face1 = graph.getFace(self.getFaceName())
       face2 = graph.getFace(toPort.getFaceName())
-      graph.mergeFace(face1.name, face2.name)
+      if kwargs.get("flip"):
+        transform = RotateX(deg2rad(180))
+      else:
+        transform = None
+      graph.mergeFace(face1.name, face2.name, transform=transform, offset=kwargs.get("offset", (0,0)), copyDecorations=True)
diff --git a/rocolib/utils/numsym.py b/rocolib/utils/numsym.py
index 42855a4..758684c 100644
--- a/rocolib/utils/numsym.py
+++ b/rocolib/utils/numsym.py
@@ -19,7 +19,7 @@ def cumsum(iterable):
 
 # Numpy mods
 def numpy_rows(x):
-    return x.shape[0]
+    return numpy.array(x)
   
 def numpy_N(x):
     return x
@@ -79,9 +79,6 @@ def sympy_difference(pts1, pts2):
 def sympy_dex(pts1, pts2, tol):
     return sympy_difference(pts1, pts2) > tol
 
-def sympy_rows(x):
-    return x.rows
-
 def sympy_pi():
     return sympy.pi
 
-- 
GitLab