Better "Expand Selection" logic. Works well with conductive components

like traces and wires and regular components like resistors and
capacitors
This commit is contained in:
bancika
2020-03-31 00:58:42 +02:00
parent f88f9ef25c
commit 09e96a03a3
6 changed files with 148 additions and 49 deletions
@@ -275,5 +275,22 @@ public class ComponentProcessor {
} }
componentTransformerMap.put(clazz.getName(), transformer); componentTransformerMap.put(clazz.getName(), transformer);
return transformer; return transformer;
}
public static boolean hasStickyPoint(IDIYComponent<?> c) {
for (int i = 0; i < c.getControlPointCount(); i++)
if (c.isControlPointSticky(0))
return true;
return false;
}
private static int touchSensitivity = 5;
public static boolean componentPointsTouch(IDIYComponent<?> c1, IDIYComponent<?> c2) {
for (int i = 0; i < c1.getControlPointCount(); i++)
for (int j = 0; j < c2.getControlPointCount(); j++)
if (c1.isControlPointSticky(i) && c2.isControlPointSticky(j) && c1.getControlPoint(i).distance(c2.getControlPoint(j)) < touchSensitivity)
return true;
return false;
} }
} }
@@ -1939,63 +1939,141 @@ public class Presenter implements IPlugInPort {
} }
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents, controlPointMap.keySet()); messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents, controlPointMap.keySet());
} }
private static boolean useNetlistForExpandSelection = false;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void expandSelection(ExpansionMode expansionMode) { public void expandSelection(ExpansionMode expansionMode) {
LOG.info(String.format("expandSelection(%s)", expansionMode)); LOG.info(String.format("expandSelection(%s)", expansionMode));
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(this.selectedComponents); List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(this.selectedComponents);
List<Netlist> netlists = extractNetlists(false); // experimental mode using netlist to expand selection. Works fine but doesn't include any connectivity components
// like traces and wires, so it's not ideal
if (netlists == null) if (useNetlistForExpandSelection) {
return; List<Netlist> netlists = extractNetlists(false);
List<Set<IDIYComponent<?>>> allGroups = NetlistAnalyzer.extractComponentGroups(netlists); if (netlists == null)
// Find control points of all selected components and all types return;
Set<String> selectedNamePrefixes = new HashSet<String>();
if (expansionMode == ExpansionMode.SAME_TYPE) { List<Set<IDIYComponent<?>>> allGroups = NetlistAnalyzer.extractComponentGroups(netlists);
for (IDIYComponent<?> component : getSelectedComponents()) { // Find control points of all selected components and all types
selectedNamePrefixes.add(ComponentProcessor.getInstance() Set<String> selectedNamePrefixes = new HashSet<String>();
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix()); if (expansionMode == ExpansionMode.SAME_TYPE) {
for (IDIYComponent<?> component : getSelectedComponents()) {
selectedNamePrefixes.add(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix());
}
} }
} // Now try to find components that intersect with at least one component
// Now try to find components that intersect with at least one component // in the pool.
// in the pool. for (IDIYComponent<?> component : getCurrentProject().getComponents()) {
for (IDIYComponent<?> component : getCurrentProject().getComponents()) { // no need to consider it, it's already in the selection
// no need to consider it, it's already in the selection if (newSelection.contains(component))
if (newSelection.contains(component)) continue;
continue; // construct a list of component groups that contain the current component
// construct a list of component groups that contain the current component List<Set<IDIYComponent<?>>> componentGroups = new ArrayList<Set<IDIYComponent<?>>>();
List<Set<IDIYComponent<?>>> componentGroups = new ArrayList<Set<IDIYComponent<?>>>(); for (Set<IDIYComponent<?>> e : allGroups)
for (Set<IDIYComponent<?>> e : allGroups) if (e.contains(component))
if (e.contains(component)) componentGroups.add(e);
componentGroups.add(e); if (componentGroups.isEmpty())
if (componentGroups.isEmpty()) continue;
continue; // Skip already selected components or ones that cannot be stuck to
// Skip already selected components or ones that cannot be stuck to // other components.
// other components. boolean matches = false;
boolean matches = false; outer: for (IDIYComponent<?> selectedComponent : this.selectedComponents) {
outer: for (IDIYComponent<?> selectedComponent : this.selectedComponents) { // try to find the selectedComponent in one of the groups
// try to find the selectedComponent in one of the groups for (Set<IDIYComponent<?>> s : componentGroups)
for (Set<IDIYComponent<?>> s : componentGroups) if (s.contains(selectedComponent)) {
if (s.contains(selectedComponent)) { matches = true;
matches = true; break outer;
break outer;
}
}
if (matches) {
switch (expansionMode) {
case ALL:
case IMMEDIATE:
newSelection.add(component);
break;
case SAME_TYPE:
if (selectedNamePrefixes.contains(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix())) {
newSelection.add(component);
} }
}
if (matches) {
switch (expansionMode) {
case ALL:
case IMMEDIATE:
newSelection.add(component);
break;
case SAME_TYPE:
if (selectedNamePrefixes.contains(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix())) {
newSelection.add(component);
}
break;
}
}
}
} else {
Set<String> selectedNamePrefixes = new HashSet<String>();
if (expansionMode == ExpansionMode.SAME_TYPE) {
// find prefixes of all selected components to bundle similar component types together
for (IDIYComponent<?> component : getSelectedComponents()) {
selectedNamePrefixes.add(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix());
}
}
// Now try to find components that intersect with at least one component
// in the pool.
for (IDIYComponent<?> component : getCurrentProject().getComponents()) {
// Skip already selected components or ones that cannot be stuck to
// other components.
ComponentArea area = drawingManager.getComponentArea(component);
if (newSelection.contains(component) || !(ComponentProcessor.hasStickyPoint(component) || (area != null
&& area.getContinuityPositiveAreas() == null)))
continue;
boolean matches = false;
for (IDIYComponent<?> selectedComponent : this.selectedComponents) {
ComponentArea selectedArea = drawingManager.getComponentArea(selectedComponent);
if (ComponentProcessor.componentPointsTouch(component, selectedComponent)) {
matches = true;
break; break;
}
if (selectedArea == null || selectedArea.getContinuityPositiveAreas() == null)
continue;
// do a rough check, if the outlines don't intersect there's no chance of a match
// so don't waste time doing the precise check
if (area.getOutlineArea() != null && selectedArea.getOutlineArea() != null &&
!area.getOutlineArea().getBounds().intersects(selectedArea.getOutlineArea().getBounds()))
continue;
// create a unified continuity area for both components
Area area1 = new Area();
for (Area a : area.getContinuityPositiveAreas())
area1.add(a);
if (area.getContinuityNegativeAreas() != null)
for(Area a : area.getContinuityNegativeAreas())
area1.subtract(a);
Area area2 = new Area();
for (Area a : selectedArea.getContinuityPositiveAreas())
area2.add(a);
if (selectedArea.getContinuityNegativeAreas() != null)
for(Area a : selectedArea.getContinuityNegativeAreas())
area2.subtract(a);
// now check the intersection, if there's something we have a match
area1.intersect(area2);
if (!area1.isEmpty()) {
matches = true;
break;
}
}
if (matches) {
switch (expansionMode) {
case ALL:
case IMMEDIATE:
newSelection.add(component);
break;
case SAME_TYPE:
if (selectedNamePrefixes.contains(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix())) {
newSelection.add(component);
}
break;
}
} }
} }
} }
@@ -2781,6 +2781,10 @@
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>Added "P-0+o (Proto) Board" component by Kristian Blåsol</description> <description>Added "P-0+o (Proto) Board" component by Kristian Blåsol</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Better "Expand Selection" logic. Works well with conductive components like traces and wires and regular components like resistors and capacitors</description>
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType> <changeType>BUG_FIX</changeType>
Binary file not shown.
Binary file not shown.
Binary file not shown.