Skip to content

Commit

Permalink
Circuit transforms with proxy contacts
Browse files Browse the repository at this point in the history
Closes #1584
  • Loading branch information
danilovesky committed Mar 1, 2024
1 parent 69e1bb0 commit 406060f
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 27 deletions.
Expand Up @@ -163,7 +163,7 @@ public VisualCircuitConnection connect(VisualNode first, VisualNode second, Math
ConnectionHelper.addControlPoints(predConnection, prefixLocationsInRootSpace);

// Original connection must be removed at this point:
// * AFTER creating a new connection from its first node (so it is not automatically cleared out)
// * AFTER creating a new connection from its first node (so first node is not automatically cleared out)
// * BEFORE creating a connection to the second node (as only one driver is allowed)
remove(connection);

Expand Down
Expand Up @@ -38,7 +38,8 @@ public boolean isApplicableTo(WorkspaceEntry we) {
public boolean isApplicableTo(VisualNode node) {
if (node instanceof VisualConnection) {
VisualConnection connection = (VisualConnection) node;
return connection.getSecond() instanceof VisualContact;
return !(connection.getFirst() instanceof VisualReplicaContact)
&& connection.getSecond() instanceof VisualContact;
}
if (node instanceof VisualContact) {
VisualContact contact = (VisualContact) node;
Expand Down
Expand Up @@ -16,6 +16,7 @@
import org.workcraft.plugins.circuit.naryformula.SplitForm;
import org.workcraft.plugins.circuit.naryformula.SplitFormGenerator;
import org.workcraft.plugins.circuit.utils.CircuitUtils;
import org.workcraft.plugins.circuit.utils.ConversionUtils;
import org.workcraft.plugins.circuit.utils.GateUtils;
import org.workcraft.types.Pair;
import org.workcraft.utils.LogUtils;
Expand Down Expand Up @@ -78,7 +79,7 @@ private static void splitComplexGate(VisualCircuit circuit, VisualFunctionCompon
Set<NodeConnectionPair> toNodeConnections = getComponentNonLoopDrivenNodes(circuit, complexGate);
Container container = (Container) complexGate.getParent();
VisualFunctionContact complexOutputContact = complexGate.getGateOutput();
circuit.remove(complexGate);
ConversionUtils.removeComponentConnections(circuit, complexGate);

Stack<Set<NodeConnectionPair>> toNodeConnectionsStack = new Stack<>();
toNodeConnectionsStack.push(toNodeConnections);
Expand All @@ -104,13 +105,16 @@ private static void splitComplexGate(VisualCircuit circuit, VisualFunctionCompon
// Update fromNodes for self-loops
fromNodeConnections.replaceAll(pair -> (pair.getFirst() == complexOutputContact)
? new NodeConnectionPair(simpleOutputContact, pair.getSecond()) : pair);

simpleOutputContact.copyStyle(complexOutputContact);
ConversionUtils.updateReplicas(circuit, complexOutputContact, simpleOutputContact);
isRootGate = false;
}
circuit.addToSelection(simpleGate);
}
}
propagateInitValues(circuit, nonRootGates);
circuit.remove(complexGate);
}

private static void connectTerminal(VisualCircuit circuit, Iterator<NodeConnectionPair> fromNodeConnectionIterator,
Expand Down
Expand Up @@ -2,22 +2,18 @@

import org.workcraft.dom.Container;
import org.workcraft.dom.visual.ConnectionHelper;
import org.workcraft.dom.visual.Replica;
import org.workcraft.dom.visual.VisualComponent;
import org.workcraft.dom.visual.VisualNode;
import org.workcraft.dom.visual.connections.VisualConnection;
import org.workcraft.exceptions.InvalidConnectionException;
import org.workcraft.plugins.circuit.VisualCircuit;
import org.workcraft.plugins.circuit.VisualContact;
import org.workcraft.plugins.circuit.VisualJoint;
import org.workcraft.plugins.circuit.VisualReplicaContact;
import org.workcraft.plugins.circuit.*;
import org.workcraft.plugins.circuit.commands.DissolveJointTransformationCommand;
import org.workcraft.utils.ModelUtils;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

public class ConversionUtils {
Expand All @@ -27,7 +23,7 @@ public static void collapseReplicaContact(VisualCircuit circuit, VisualReplicaCo
Point2D replicaPositionInRootSpace = replica.getRootSpacePosition();
Container container = (Container) replica.getParent();
Set<VisualConnection> outgoingConnections = circuit.getConnections(replica).stream()
.filter(c -> c.getFirst() == replica).collect(Collectors.toSet());
.filter(connection -> connection.getFirst() == replica).collect(Collectors.toSet());

if (outgoingConnections.size() > 1) {
VisualJoint joint = circuit.createJoint(container);
Expand Down Expand Up @@ -99,4 +95,42 @@ public static VisualConnection replicateDriverContact(VisualCircuit circuit, Vis
return null;
}

public static void updateReplicas(VisualCircuit circuit, VisualContact oldContact, VisualContact newContact) {
ArrayList<Replica> oldReplicas = new ArrayList<>(oldContact.getReplicas());
for (Replica oldReplica : oldReplicas) {
if (oldReplica instanceof VisualReplicaContact) {
VisualReplicaContact oldReplicaContact = (VisualReplicaContact) oldReplica;
Container container = (Container) oldReplicaContact.getParent();
VisualReplicaContact newReplicaContact
= circuit.createVisualReplica(newContact, VisualReplicaContact.class, container);

newReplicaContact.copyStyle(oldReplicaContact);
newReplicaContact.copyPosition(oldReplicaContact);

Set<VisualConnection> oldReplicaConnections = circuit.getConnections(oldReplicaContact).stream()
.filter(connection -> connection.getFirst() == oldReplicaContact).collect(Collectors.toSet());

for (VisualConnection oldReplicaConnection : oldReplicaConnections) {
VisualNode secondNode = oldReplicaConnection.getSecond();
circuit.remove(oldReplicaConnection);
try {
VisualConnection newReplicaConnection = circuit.connect(newReplicaContact, secondNode);
newReplicaConnection.copyStyle(oldReplicaConnection);
newReplicaConnection.copyShape(oldReplicaConnection);
} catch (InvalidConnectionException e) {
throw new RuntimeException(e.getMessage());
}
}
}
}
}

public static void removeComponentConnections(VisualCircuit circuit, VisualFunctionComponent component) {
Set<VisualConnection> unneededConnections = new HashSet<>();
for (VisualContact contact : component.getVisualContacts()) {
unneededConnections.addAll(circuit.getConnections(contact));
}
circuit.remove(unneededConnections);
}

}
Expand Up @@ -2,10 +2,7 @@

import org.workcraft.dom.Container;
import org.workcraft.dom.Node;
import org.workcraft.dom.visual.ConnectionHelper;
import org.workcraft.dom.visual.MixUtils;
import org.workcraft.dom.visual.VisualComponent;
import org.workcraft.dom.visual.VisualNode;
import org.workcraft.dom.visual.*;
import org.workcraft.dom.visual.connections.VisualConnection;
import org.workcraft.exceptions.InvalidConnectionException;
import org.workcraft.formula.*;
Expand Down Expand Up @@ -69,7 +66,7 @@ public static void insertGateAfter(VisualCircuit circuit, VisualCircuitComponent
} catch (InvalidConnectionException e) {
LogUtils.logWarning(e.getMessage());
}
for (VisualComponent succComponent: succComponents) {
for (VisualComponent succComponent : succComponents) {
VisualConnection connection = circuit.getConnection(predContact, succComponent);
LinkedList<Point2D> suffixControlPoints = ConnectionHelper.getSuffixControlPoints(connection, pos);
circuit.remove(connection);
Expand All @@ -81,6 +78,7 @@ public static void insertGateAfter(VisualCircuit circuit, VisualCircuitComponent
LogUtils.logWarning(e.getMessage());
}
}
ConversionUtils.updateReplicas(circuit, predContact, outputContact);
}

public static void insertGateWithin(VisualCircuit circuit, VisualCircuitComponent component,
Expand All @@ -107,15 +105,22 @@ public static void insertGateWithin(VisualCircuit circuit, VisualCircuitComponen
outputContact.setDirection(direction);

LinkedList<Point2D> prefixControlPoints = ConnectionHelper.getPrefixControlPoints(connection, pos);
LinkedList<Point2D> suffixControlPoints = ConnectionHelper.getSuffixControlPoints(connection, pos);
circuit.remove(connection);
try {
VisualConnection inputConnection = circuit.connect(fromNode, inputContact);
ConnectionHelper.addControlPoints(inputConnection, prefixControlPoints);
} catch (InvalidConnectionException e) {
throw new RuntimeException(e.getMessage());
}
LinkedList<Point2D> suffixControlPoints = ConnectionHelper.getSuffixControlPoints(connection, pos);
// Original connection must be removed at this point:
// * AFTER creating a new connection from its first node (so first node is not automatically cleared out)
// * BEFORE creating a connection to the second node (as only one driver is allowed)
circuit.remove(connection);
try {
VisualConnection outputConnection = circuit.connect(outputContact, toNode);
ConnectionHelper.addControlPoints(outputConnection, suffixControlPoints);
} catch (InvalidConnectionException e) {
LogUtils.logWarning(e.getMessage());
throw new RuntimeException(e.getMessage());
}
}

Expand Down
Expand Up @@ -3,6 +3,7 @@
import org.workcraft.dom.Node;
import org.workcraft.dom.visual.*;
import org.workcraft.dom.visual.connections.ConnectionUtils;
import org.workcraft.dom.visual.connections.ControlPoint;
import org.workcraft.dom.visual.connections.VisualConnection;
import org.workcraft.plugins.circuit.*;
import org.workcraft.utils.Hierarchy;
Expand Down Expand Up @@ -47,21 +48,25 @@ public static void offsetComponentsFromContact(VisualCircuit circuit, VisualCont
double xSpace = dx * (space - minSpace);
double ySpace = dy * (space - minSpace);

Collection<VisualComponent> components = Hierarchy.getDescendantsOfType(circuit.getRoot(),
VisualComponent.class, node -> !(node instanceof VisualPage)
Collection<VisualTransformableNode> transformableNodes = Hierarchy.getDescendantsOfType(circuit.getRoot(),
VisualTransformableNode.class, node -> !(node instanceof VisualPage)
&& !(node instanceof ControlPoint)
&& !((node instanceof VisualContact) && ((VisualContact) node).isPin()));

for (VisualComponent component : components) {
Rectangle2D bb = component.getInternalBoundingBoxInLocalSpace();
double x = component.getRootSpaceX();
for (VisualTransformableNode transformableNode : transformableNodes) {
Rectangle2D bb = (transformableNode instanceof VisualComponent)
? ((VisualComponent) transformableNode).getInternalBoundingBoxInLocalSpace()
: transformableNode.getBoundingBoxInLocalSpace();

double x = transformableNode.getRootSpaceX();
double xBorder = x + bb.getX() + ((dx < 0) ? bb.getWidth() : 0.0);
if ((xBorder - x0) * dx > 0) {
component.setRootSpaceX(x + xSpace);
transformableNode.setRootSpaceX(x + xSpace);
}
double y = component.getRootSpaceY();
double y = transformableNode.getRootSpaceY();
double yBorder = y + bb.getY() + ((dy < 0) ? bb.getHeight() : 0.0);
if ((yBorder - y0) * dy > 0) {
component.setRootSpaceY(y + ySpace);
transformableNode.setRootSpaceY(y + ySpace);
}
}
}
Expand Down

0 comments on commit 406060f

Please sign in to comment.