Package com.cburch.logisim.circuit

Source Code of com.cburch.logisim.circuit.WireRepair$MergeSets

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.circuit;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import com.cburch.logisim.comp.Component;
import com.cburch.logisim.data.Location;

class WireRepair extends CircuitTransaction {

  private static class MergeSets {
    private final HashMap<Wire,ArrayList<Wire>> map;
   
    MergeSets() {
      map = new HashMap<Wire,ArrayList<Wire>>();
    }
   
    void merge(Wire a, Wire b) {
      ArrayList<Wire> set0 = map.get(a);
      ArrayList<Wire> set1 = map.get(b);
      if (set0 == null && set1 == null) {
        set0 = new ArrayList<Wire>(2);
        set0.add(a);
        set0.add(b);
        map.put(a, set0);
        map.put(b, set0);
      } else if (set0 == null && set1 != null) {
        set1.add(a);
        map.put(a, set1);
      } else if (set0 != null && set1 == null) {
        set0.add(b);
        map.put(b, set0);
      } else if (set0 != set1) { // neither is null, and they are different
        if (set0.size() > set1.size()) { // ensure set1 is the larger
          ArrayList<Wire> temp = set0;
          set0 = set1;
          set1 = temp;
        }
        set1.addAll(set0);
        for (Wire w : set0) {
          map.put(w, set1);
        }
      }
    }
   
    Collection<ArrayList<Wire>> getMergeSets() {
      IdentityHashMap<ArrayList<Wire>,Boolean> lists;
      lists = new IdentityHashMap<ArrayList<Wire>,Boolean>();
      for (ArrayList<Wire> list : map.values()) {
        lists.put(list, Boolean.TRUE);
      }
      return lists.keySet();
    }
  }

  private Circuit circuit;
 
  public WireRepair(Circuit circuit) {
    this.circuit = circuit;
  }

  @Override
  protected Map<Circuit,Integer> getAccessedCircuits() {
    return Collections.singletonMap(circuit, READ_WRITE);
  }

  @Override
  protected void run(CircuitMutator mutator) {
    doMerges(mutator);
    doOverlaps(mutator);
    doSplits(mutator);
  }
 
  /* for debugging:
  private void printWires(String prefix, PrintStream out) {
    boolean first = true;
    for (Wire w : circuit.getWires()) {
      if (first) {
        out.println(prefix + ": " + w);
        first = false;
      } else {
        out.println("      " + w);
      }
    }
    out.println(prefix + ": none");
  }
  */
 
  private void doMerges(CircuitMutator mutator) {
    MergeSets sets = new MergeSets();
    for (Location loc : circuit.wires.points.getSplitLocations()) {
      Collection<?> at = circuit.getComponents(loc);
      if (at.size() == 2) {
        Iterator<?> atit = at.iterator();
        Object at0 = atit.next();
        Object at1 = atit.next();
        if (at0 instanceof Wire && at1 instanceof Wire) {
          Wire w0 = (Wire) at0;
          Wire w1 = (Wire) at1;
          if (w0.isParallel(w1)) {
            sets.merge(w0, w1);
          }
        }
      }
    }

    ReplacementMap repl = new ReplacementMap();
    for (ArrayList<Wire> mergeSet : sets.getMergeSets()) {
      if (mergeSet.size() > 1) {
        ArrayList<Location> locs = new ArrayList<Location>(2 * mergeSet.size());
        for (Wire w : mergeSet) {
          locs.add(w.getEnd0());
          locs.add(w.getEnd1());
        }
        Collections.sort(locs);
        Location e0 = locs.get(0);
        Location e1 = locs.get(locs.size() - 1);
        Wire wnew = Wire.create(e0, e1);
        Collection<Wire> wset = Collections.singleton(wnew);

        for (Wire w : mergeSet) {
          if (!w.equals(wset)) {
            repl.put(w, wset);
          }
        }
      }
    }
    mutator.replace(circuit, repl);
  }
 
  private void doOverlaps(CircuitMutator mutator) {
    HashMap<Location,ArrayList<Wire>> wirePoints;
    wirePoints = new HashMap<Location,ArrayList<Wire>>();
    for (Wire w : circuit.getWires()) {
      for (Location loc : w) {
        ArrayList<Wire> locWires = wirePoints.get(loc);
        if (locWires == null) {
          locWires = new ArrayList<Wire>(3);
          wirePoints.put(loc, locWires);
        }
        locWires.add(w);
      }
    }
   
    MergeSets mergeSets = new MergeSets();
    for (ArrayList<Wire> locWires : wirePoints.values()) {
      if (locWires.size() > 1) {
        for (int i = 0, n = locWires.size(); i < n; i++) {
          Wire w0 = locWires.get(i);
          for (int j = i + 1; j < n; j++) {
            Wire w1 = locWires.get(j);
            if (w0.overlaps(w1, false)) {
              mergeSets.merge(w0, w1);
            }
          }
        }
      }
    }

    ReplacementMap replacements = new ReplacementMap();
    Set<Location> splitLocs = circuit.wires.points.getSplitLocations();
    for (ArrayList<Wire> mergeSet : mergeSets.getMergeSets()) {
      if (mergeSet.size() > 1) {
        doMergeSet(mergeSet, replacements, splitLocs);
      }
    }
    mutator.replace(circuit, replacements);
  }
 
  private void doMergeSet(ArrayList<Wire> mergeSet, ReplacementMap replacements,
      Set<Location> splitLocs) {
    TreeSet<Location> ends = new TreeSet<Location>();
    for (Wire w : mergeSet) {
      ends.add(w.getEnd0());
      ends.add(w.getEnd1());
    }
    Wire whole = Wire.create(ends.first(), ends.last());

    TreeSet<Location> mids = new TreeSet<Location>();
    mids.add(whole.getEnd0());
    mids.add(whole.getEnd1());
    for (Location loc : whole) {
      if (splitLocs.contains(loc)) {
        for (Component comp : circuit.getComponents(loc)) {
          if (!mergeSet.contains(comp)) {
            mids.add(loc);
            break;
          }
        }
      }
    }
   
    ArrayList<Wire> mergeResult = new ArrayList<Wire>();
    if (mids.size() == 2) {
      mergeResult.add(whole);
    } else {
      Location e0 = mids.first();
      for (Location e1 : mids) {
        mergeResult.add(Wire.create(e0, e1));
        e0 = e1;
      }
    }
   
    for (Wire w : mergeSet) {
      ArrayList<Component> wRepl = new ArrayList<Component>(2);
      for (Wire w2 : mergeResult) {
        if (w2.overlaps(w, false)) {
          wRepl.add(w2);
        }
      }
      replacements.put(w, wRepl);
    }
  }
 
  private void doSplits(CircuitMutator mutator) {
    Set<Location> splitLocs = circuit.wires.points.getSplitLocations();
    ReplacementMap repl = new ReplacementMap();
    for (Wire w : circuit.getWires()) {
      Location w0 = w.getEnd0();
      Location w1 = w.getEnd1();
      ArrayList<Location> splits = null;
      for (Location loc : splitLocs) {
        if (w.contains(loc) && !loc.equals(w0) && !loc.equals(w1)) {
          if (splits == null) splits = new ArrayList<Location>();
          splits.add(loc);
        }
      }
      if (splits != null) {
        splits.add(w1);
        Collections.sort(splits);
        Location e0 = w0;
        ArrayList<Wire> subs = new ArrayList<Wire>(splits.size());
        for (Location e1 : splits) {
          subs.add(Wire.create(e0, e1));
          e0 = e1;
        }
        repl.put(w, subs);
      }
    }
    mutator.replace(circuit, repl);
  }
}
TOP

Related Classes of com.cburch.logisim.circuit.WireRepair$MergeSets

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.