/* PseudoCode Interpreted Language (PCIL): Part of the algoviz@vt collection of algorithm visualizations. Copyright (C) 2008 Brandon Malone, Frank Hadlock This file is part of the PseudoCode Interpreted Language. PseudoCode Interpreted Language is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PseudoCode Interpreted Language is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with PseudoCode Interpreted Language. If not, see . */ /* * PrimitiveEdge.java * * Created on March 6, 2008, 6:50 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package dynamicmvc; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.ArrayList; import java.util.HashMap; import javax.swing.JComponent; import javax.swing.JPanel; /** * * @author Brandon */ public class PrimitiveEdge extends Primitive { public static String pseudocodeTypeName() { return "Edge"; } public String getType() { return pseudocodeTypeName(); } // private String value; private String name; private String color; private PrimitivePointer weight; private PrimitivePointer first; private PrimitivePointer second; private PrimitivePointer g; // // public Primitive copy() { PrimitiveEdge i = new PrimitiveEdge(getName(), getValue(), getColor(), getFirst(), getSecond(), getWeight()); return i; } public Primitive deepCopy(HashMap alreadyCopiedAddresses) throws DynamicMVCException { PrimitivePointer p = getPointer(); if (alreadyCopiedAddresses.containsKey(Integer.valueOf(p.getAddress()))) { return PrimitiveFactory.getFromMemory(alreadyCopiedAddresses.get(p.getAddress())); } PrimitivePointer pp = PrimitiveFactory.create(pseudocodeTypeName(), name); alreadyCopiedAddresses.put(p.getAddress(), pp.getAddress()); PrimitiveEdge i = (PrimitiveEdge) pp.dereference(); i.setName(name); i.setValue(value); i.setColor(color); i.setFirst(first.deepCopy(alreadyCopiedAddresses)); i.setSecond(second.deepCopy(alreadyCopiedAddresses)); i.setWeight(weight.deepCopy(alreadyCopiedAddresses)); if (g != null) { i.setG(g.deepCopy(alreadyCopiedAddresses)); } deepCopyDefinedProperties(i, alreadyCopiedAddresses); return i; } public boolean deepEquals(Primitive p) throws DynamicMVCException { if (!(p instanceof PrimitiveEdge)) { DynamicController.errorMessage = "Expecting Edge, but found " + p.getType(); return false; } PrimitiveEdge e = (PrimitiveEdge) p; if (!first.deepEquals(e.getFirst())) { return false; } if (!second.deepEquals(e.getSecond())) { return false; } if (!weight.deepEquals(e.getWeight())) { return false; } return super.deepEqualsDefinedProperties(p); } public PrimitivePointer get(String name) throws DynamicMVCException { if (name.equalsIgnoreCase("edges")) { return getEdges(); } return super.get(name); } public void set(Primitive other) throws DynamicMVCException { // if other is an integer, copy its values if (other instanceof PrimitiveEdge) { PrimitiveEdge o = (PrimitiveEdge) other; //setName(o.getName()); setValue(o.getValue()); setName(o.getName()); setColor(o.getColor()); setFirst(o.getFirst()); setSecond(o.getSecond()); setWeight(o.getWeight()); } else { // otherwise, throw an DynamicMVCException throw new DynamicMVCException("Invalid assignment."); } } /** Creates a new instance of PrimitiveEdge */ public PrimitiveEdge(String name, String value, String color, PrimitivePointer first, PrimitivePointer second, PrimitivePointer weight) { super(); PrimitivePointer f = first.copy(); PrimitivePointer s = second.copy(); PrimitivePointer w = weight.copy(); f.setName("first"); s.setName("second"); w.setName("weight"); setName(name); setValue(value); setColor(color); setFirst(f); setSecond(s); setWeight(w); } /** Creates a new instance of PrimitiveEdge */ public PrimitiveEdge(PrimitivePointer first, PrimitivePointer second) { super(); PrimitivePointer f = first.copy(); PrimitivePointer s = second.copy(); f.setName("first"); s.setName("second"); setName(""); setValue(""); setColor(""); setFirst(f); setSecond(s); } public PrimitiveEdge(String value) { super(); setName(""); setValue(value); } public PrimitiveEdge() { super(); setName(""); setValue(""); setFirst(PrimitiveFactory.create(PrimitiveVertex.pseudocodeTypeName(), "first")); setSecond(PrimitiveFactory.create(PrimitiveVertex.pseudocodeTypeName(), "second")); setWeight(PrimitiveFactory.create(PrimitiveInteger.pseudocodeTypeName(), "weight")); } // // public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public PrimitivePointer getFirst() { return first; } public void setFirst(String first) { this.first = ((PrimitiveGraph) getG().dereference()).getVertex(first).copy(); this.first.setName("first"); // and set this super.set("first", this.first); } public void setFirst(PrimitivePointer first) { this.first = first.copy(); this.first.setName("first"); super.set("first", this.first); } public PrimitivePointer getSecond() { return second; } public void setSecond(String second) { this.second = ((PrimitiveGraph) getG().dereference()).getVertex(second).copy(); this.second.setName("second"); super.set("second", this.second); } public void setSecond(PrimitivePointer second) { this.second = second.copy(); this.second.setName("second"); super.set("second", this.second); } public PrimitivePointer getWeight() { return weight; } public void setWeight(PrimitivePointer weight) { this.weight = weight.copy(); this.weight.setName("weight"); super.set("weight", this.weight); } public PrimitivePointer getEdges() { PrimitivePointer l = PrimitiveFactory.create(PrimitiveList.pseudocodeTypeName(), "edges"); PrimitiveList newList = (PrimitiveList) l.dereference(); PrimitivePointer firstEdgeList = ((PrimitiveVertex) first.dereference()).getEdges(); PrimitivePointer secondEdgeList = ((PrimitiveVertex) second.dereference()).getEdges(); PrimitiveList fl = ((PrimitiveList) firstEdgeList.dereference()); PrimitiveList sl = ((PrimitiveList) secondEdgeList.dereference()); for (PrimitivePointer e : fl.getList()) { newList.add(e); } for (PrimitivePointer e : sl.getList()) { newList.add(e); } return l; } // // public void populateFromEditComponentWrapper(JComponent editComponentWrapper) throws DynamicMVCException { /* String firstName = first.getEditComponentName(); JComponent firstChild = (JComponent)View.getComponent(editComponentWrapper, firstName); first.populateFromEditComponentWrapper(firstChild); String secondName = second.getEditComponentName(); JComponent secondChild = (JComponent)View.getComponent(editComponentWrapper, secondName); second.populateFromEditComponentWrapper(secondChild); String weightName = weight.getEditComponentName(); JComponent weightChild = (JComponent)View.getComponent(editComponentWrapper, weightName); weight.populateFromEditComponentWrapper(weightChild); */ // need to populate properties JComponent propertiesComponent = (JComponent) View.getComponent(editComponentWrapper, this.getPropertiesComponentName()); super.populateDefinedProperties(propertiesComponent); } public String getEditComponentWrapperName() { return "pnl" + getName(); } public String getEditComponentValue() { return "txt" + getName() + "value"; } public String getFirstNodeTextBox() { return "txt" + getName() + "first"; } public String getSecondNodeTextBox() { return "txt" + getName() + "second"; } public JComponent getEditComponent() { // wrap everything in a panel JPanel wrapper = new JPanel(); wrapper.setName(getEditComponentWrapperName()); /* String fn = first.getName(); String sn = second.getName(); String wn = weight.getName(); first.setName("first"); second.setName("second"); weight.setName("weight"); JComponent firstWrapper = first.getEditComponent(); JComponent secondWrapper = second.getEditComponent(); JComponent weightWrapper = weight.getEditComponent(); first.setName(fn); second.setName(sn); weight.setName(wn); wrapper.add(firstWrapper); wrapper.add(secondWrapper); wrapper.add(weightWrapper); */ super.addEditDefinedProperties(wrapper); return wrapper; } public JComponent getReadOnlyComponent() { // wrap everything in a panel JPanel wrapper = new JPanel(); wrapper.setName(getEditComponentWrapperName()); String fn = ""; if (first != null) { fn = first.getName(); first.setName("first"); JComponent firstWrapper = first.getReadOnlyComponent(); first.setName(fn); wrapper.add(firstWrapper); } String sn = ""; if (second != null) { sn = second.getName(); second.setName("second"); JComponent secondWrapper = second.getReadOnlyComponent(); second.setName(sn); wrapper.add(secondWrapper); } String wn = ""; if (weight != null) { wn = weight.getName(); weight.setName("weight"); JComponent weightWrapper = weight.getReadOnlyComponent(); weight.setName(wn); wrapper.add(weightWrapper); } return wrapper; } public void draw(Graphics g) { int x1 = ((PrimitiveInteger) ((PrimitiveVertex) getFirst().dereference()).getX().dereference()).getValue(); int y1 = ((PrimitiveInteger) ((PrimitiveVertex) getFirst().dereference()).getY().dereference()).getValue(); int x2 = ((PrimitiveInteger) ((PrimitiveVertex) getSecond().dereference()).getX().dereference()).getValue(); int y2 = ((PrimitiveInteger) ((PrimitiveVertex) getSecond().dereference()).getY().dereference()).getValue(); g.setColor(Color.GREEN); double angle = getAngleBetween(x1, y1, x2, y2); // if from left to right (x1 < x2), adjust down a little bit // otherwise, adjust up a bit // hack code if (x1 < x2) { y1 += PrimitiveVertex.getRadius()/2 * Math.cos(angle); y2 += PrimitiveVertex.getRadius()/2 * Math.cos(angle); } else { y1 -= PrimitiveVertex.getRadius()/2 * Math.cos(angle - Math.PI); y2 -= PrimitiveVertex.getRadius()/2 * Math.cos(angle - Math.PI); } if (angle%Math.PI >= 3*Math.PI / 8.0 && angle%Math.PI <= 5*Math.PI/8.0) { x1 += PrimitiveVertex.getRadius()/2 * Math.sin(angle); x2 += PrimitiveVertex.getRadius()/2 * Math.sin(angle); } else { x1 += PrimitiveVertex.getRadius()/2 * Math.sin(angle - Math.PI); x2 += PrimitiveVertex.getRadius()/2 * Math.sin(angle - Math.PI); } if (this.getG().dereference() instanceof PrimitiveDirectedGraph) { g.setColor(Color.BLUE); drawArrow(x1, y1, x2, y2, g); } else { g.drawLine(x1, y1, x2, y2); } // adjust the position of the text // hack code if (x1 < x2) { y1 += 15; y2 += 15; } else { y1 -= 5; y2 -= 5; } if (angle >= 3*Math.PI / 8.0 && angle <= 5*Math.PI/8.0) { x1 += 10; x2 += 10; } else if (angle >= 11*Math.PI / 8.0 && angle <= 13*Math.PI/8.0) { x1 -= 15; x2 -= 15; } PrimitiveInteger w = ((PrimitiveInteger) weight.dereference()); g.drawString(String.valueOf(w.getValue()), (x1 + x2) / 2, (y1 + y2) / 2); } private double getAngleBetween(int x1, int y1, int x2, int y2) { Point parentPoint = new Point(x1, y1); Point childPoint = new Point(x2, y2); int parentX = (int) parentPoint.getX(); int parentY = (int) parentPoint.getY(); int childX = (int) childPoint.getX(); int childY = (int) childPoint.getY(); Point referencePoint = new Point((int) (Integer.MAX_VALUE), (int) childPoint.getY()); double a = parentPoint.distance(childPoint); double b = parentPoint.distance(referencePoint); double c = childPoint.distance(referencePoint); double beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)); if (parentY > childY) { beta = (2.0 * Math.PI) - beta; } return beta; } private void drawArrow(int x1, int y1, int x2, int y2, Graphics g) { // draw the line Point parentPoint = new Point(x1, y1); Point childPoint = new Point(x2, y2); int parentX = (int) parentPoint.getX(); int parentY = (int) parentPoint.getY(); int childX = (int) childPoint.getX(); int childY = (int) childPoint.getY(); /* + 10000 cause it makes it work */ Point referencePoint = new Point((int) (childPoint.getX() + 10000), (int) childPoint.getY()); double a = parentPoint.distance(childPoint); double b = parentPoint.distance(referencePoint); double c = childPoint.distance(referencePoint); double beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)); if (parentY > childY) { beta = (2.0 * Math.PI) - beta; } int arrowX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius())); int arrowY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius())); arrowX = childX - arrowX; arrowY = childY - arrowY; g.drawLine(parentX, parentY, arrowX, arrowY); Point arrowPoint = new Point(arrowX, arrowY); // draw the arrow head referencePoint = new Point((int) (arrowPoint.getX() + 10000), (int) arrowPoint.getY()); a = parentPoint.distance(arrowPoint); b = parentPoint.distance(referencePoint); c = arrowPoint.distance(referencePoint); beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)) + ((1.0 / 6.0) * Math.PI); if (parentY > arrowY) { beta = (2.0 * Math.PI) - beta; } int arrowTailX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius())); int arrowTailY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius())); arrowTailX = (int) arrowPoint.getX() - arrowTailX; arrowTailY = (int) arrowPoint.getY() - arrowTailY; g.drawLine(arrowX, arrowY, arrowTailX, arrowTailY); beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)) - ((1.0 / 6.0) * Math.PI); if (parentY > arrowY) { beta = (2.0 * Math.PI) - beta; } arrowTailX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius())); arrowTailY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius())); arrowTailX = (int) arrowPoint.getX() - arrowTailX; arrowTailY = (int) arrowPoint.getY() - arrowTailY; g.drawLine(arrowX, arrowY, arrowTailX, arrowTailY); } // public Object execute(String methodName, ArrayList arguments) throws DynamicMVCException { // is this a method of mine? if (methodName.equalsIgnoreCase("equals")) { return equals(arguments); } else if (methodName.equalsIgnoreCase("notEqual")) { return !equals(arguments); } else if (methodName.equalsIgnoreCase("assign")) { assign(arguments); return null; } else if (methodName.equalsIgnoreCase("hasEndPoint")) { return hasEndPoint(arguments); } else { throw new DynamicMVCException("Invalid method name:'" + methodName + "' on object '" + getName() + "'."); } } public PrimitivePointer findOtherVertex(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 1) { PrimitiveVertex v = (PrimitiveVertex) arguments.get(0).dereference(); return findOtherVertex(v); } else { throw new DynamicMVCException("Wrong number of arguments."); } } public PrimitivePointer findOtherVertex(PrimitiveVertex v) throws DynamicMVCException { PrimitivePointer p = v.getPointer(); if (this.first.equals(p)) { return second; } else if (this.second.equals(p)) { return first; } else { throw new DynamicMVCException("Edge does not contain vertex."); } } public PrimitivePointer hasEndPoint(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 1) { PrimitivePointer v1 = arguments.get(0); return hasEndPoint(v1); } else { throw new DynamicMVCException("Wrong number of arguments."); } } public PrimitivePointer hasEndPoint(PrimitivePointer v) throws DynamicMVCException { if(v.dereference() instanceof PrimitiveVertex) { return hasEndPoint((PrimitiveVertex)v.dereference()); } throw new DynamicMVCException("Wrong type of argument. Expecting Vertex but found " + v.dereference().getType()); } public PrimitivePointer hasEndPoint(PrimitiveVertex v) throws DynamicMVCException { PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "hasEndPoint"); PrimitiveBoolean bool = (PrimitiveBoolean)b.dereference(); bool.setValue(first.deepEquals(v) || second.deepEquals(v)); return b; } public PrimitivePointer hasEndPoints(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 2) { PrimitiveVertex v1 = (PrimitiveVertex) arguments.get(0).dereference(); PrimitiveVertex v2 = (PrimitiveVertex) arguments.get(1).dereference(); return hasEndPoints(v1, v2); } else { throw new DynamicMVCException("Wrong number of arguments."); } } public PrimitivePointer hasEndPoints(PrimitiveVertex v1, PrimitiveVertex v2) { if (first.equals(v1) && second.equals(v2)) { PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(true); return b; } if (getG().dereference() instanceof PrimitiveGraph) { if (first.equals(v2) && second.equals(v1)) { PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(true); return b; } } PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(false); return b; } public PrimitivePointer hasEndPoints(PrimitivePointer v1, PrimitivePointer v2) { PrimitiveVertex pv1 = (PrimitiveVertex) v1.dereference(); PrimitiveVertex pv2 = (PrimitiveVertex) v2.dereference(); PrimitiveVertex vFirst = (PrimitiveVertex) first.dereference(); PrimitiveVertex vSecond = (PrimitiveVertex) second.dereference(); try { if (vFirst.equals(pv1) && vSecond.equals(pv2)) { PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(true); return b; } } catch (DynamicMVCException ex) { ex.printStackTrace(); } if (getG().dereference() instanceof PrimitiveGraph) { try { if (vFirst.equals(pv2) && vSecond.equals(pv1)) { PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(true); return b; } } catch (DynamicMVCException ex) { ex.printStackTrace(); } } PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), ""); ((PrimitiveBoolean) b.dereference()).setValue(false); return b; } public int compareTo(Object o) throws DynamicMVCException { if (o instanceof PrimitivePointer) { PrimitiveEdge i = (PrimitiveEdge) ((PrimitivePointer) o).dereference(); return compareTo(i); } throw new DynamicMVCException("Invalid comparison"); } public boolean equals(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 1) { PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference(); return equals(i); } throw new DynamicMVCException("Wrong number of arguments."); } public boolean equals(PrimitiveEdge i) { return (compareTo(i) == 0); } public int compareTo(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 1) { PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference(); return compareTo(i); } throw new DynamicMVCException("Wrong number of arguments."); } public int compareTo(PrimitiveEdge i) { String otherName = i.getName(); return getName().compareTo(otherName); } public void assign(ArrayList arguments) throws DynamicMVCException { if (arguments.size() == 1) { PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference(); assign(i); } throw new DynamicMVCException("Wrong number of arguments."); } public void assign(PrimitiveEdge i) throws DynamicMVCException { throw new DynamicMVCException("Deprecated method"); /*String otherName = i.getName(); String otherValue = i.getValue(); String otherColor = i.getColor(); PrimitiveVertex otherFirst = i.getFirst(); PrimitiveVertex otherSecond = i.getSecond(); setName(otherName); setValue(otherValue); setColor(otherColor); setFirst(otherFirst); setSecond(otherSecond); **/ } public String toString() { return getName() + ": " + getValue() + ": " + getColor() + ": " + ((PrimitiveVertex) first.dereference()).getName() + ": " + ((PrimitiveVertex) second.dereference()).getName(); } public int compareTo(Primitive p) throws DynamicMVCException { if (p instanceof PrimitiveEdge) { return name.compareTo(p.getName()); } else { throw new DynamicMVCException("Invalid comparison."); } } public PrimitiveString toPrimitiveString() { PrimitiveString s = (PrimitiveString) (PrimitiveFactory.create(PrimitiveString.pseudocodeTypeName(), "s").dereference()); s.setValue(toString()); return s; } public PrimitivePointer getG() { return g; } public void setG(PrimitivePointer g) { this.g = g; } }