import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import java.io.*; import java.util.*; public class Graph { private String label; private ArrayList nodes; public Graph() { this("", new ArrayList()); } public Graph(String aLabel) { this(aLabel, new ArrayList()); } public Graph(String aLabel, ArrayList initialNodes) { label = aLabel; nodes = initialNodes; } public ArrayList getNodes() { return nodes; } public String getLabel() { return label; } public void setLabel(String newLabel) { label = newLabel; } // Graphs look like this: label(6 nodes, 15 edges) public String toString() { return(label + "(" + nodes.size() + " nodes, " + getEdges().size() + " edges)"); } // Get all the edges of the graph by asking the nodes for them public ArrayList getEdges() { ArrayList edges = new ArrayList(); for (Node n: nodes) { for (Edge e: n.incidentEdges()) { if (!edges.contains(e)) //so that it is not added twice edges.add(e); } } return edges; } // Add the given Node to the graph public void addNode(Node aNode) { nodes.add(aNode); } // Add an edge to the graph from the given start Node to the end Node public void addEdge(Node start, Node end) { // First make the edge Edge anEdge = new Edge(start, end); // Now tell the nodes about the edge start.addIncidentEdge(anEdge); end.addIncidentEdge(anEdge); } // Add an edge by connecting the Nodes with the given labels public void addEdge(String startLabel, String endLabel) { Node start = nodeNamed(startLabel); Node end = nodeNamed(endLabel); if ((start != null) && (end != null)) addEdge(start, end); } // Delete the given Edge from the graph public void deleteEdge(Edge anEdge) { // Just ask the nodes to remove it anEdge.getStartNode().incidentEdges().remove(anEdge); anEdge.getEndNode().incidentEdges().remove(anEdge); } // Delete the given Node from the graph public void deleteNode(Node aNode) { // Remove the opposite node's incident edges for (Edge e: aNode.incidentEdges()) e.otherEndFrom(aNode).incidentEdges().remove(e); nodes.remove(aNode); // Remove the node now } // Find and return the Node with the given label public Node nodeNamed(String aLabel) { for (Node n: nodes) if (n.getLabel().equals(aLabel)) return n; return null; // If we don't find one } public static Graph example() { Graph myMap = new Graph("Ontario and Quebec"); myMap.addNode(new Node("Ottawa", new Point2D(250,100))); myMap.addNode(new Node("Toronto", new Point2D(100,120))); myMap.addNode(new Node("Kingston", new Point2D(200,130))); myMap.addNode(new Node("Montreal", new Point2D(300,70))); myMap.addEdge("Ottawa", "Toronto"); myMap.addEdge("Ottawa", "Montreal"); myMap.addEdge("Ottawa", "Kingston"); myMap.addEdge("Kingston", "Toronto"); return myMap; } public void draw(GraphicsContext aPen) { ArrayList edges = getEdges(); for (Edge e: edges) // Draw the edges first e.draw(aPen); for (Node n: nodes) // Draw the nodes second n.draw(aPen); } // Return the first node in which point p is contained, if none, return null public Node nodeAt(double x, double y) { for (int i=nodes.size()-1; i>=0; i--) { Node n = nodes.get(i); Point2D c = n.getLocation(); double d = (x - c.getX()) * (x - c.getX()) + (y - c.getY()) * (y - c.getY()); if (d <= (Node.RADIUS*Node.RADIUS)) return n; } return null; } // Return first edge in which point p is near midpoint; if none, return null public Edge edgeAt(double x, double y) { for (Edge e: getEdges()) { Node n1 = e.getStartNode(); Node n2 = e.getEndNode(); double xDiff = n2.getLocation().getX() - n1.getLocation().getX(); double yDiff = n2.getLocation().getY() - n1.getLocation().getY(); double distance = Math.abs(xDiff*(n1.getLocation().getY() - y) - (n1.getLocation().getX() - x)*yDiff) / Math.sqrt(xDiff*xDiff + yDiff*yDiff); if (distance <= 5) { if (Math.abs(xDiff) > Math.abs(yDiff)) { if (((x < n1.getLocation().getX()) && (x > n2.getLocation().getX())) || ((x > n1.getLocation().getX()) && (x < n2.getLocation().getX()))) return e; } else if (((y < n1.getLocation().getY()) && (y > n2.getLocation().getY())) || ((y > n1.getLocation().getY()) && (y < n2.getLocation().getY()))) return e; } } return null; } // Get all the nodes that are selected public ArrayList selectedNodes() { ArrayList selected = new ArrayList(); for (Node n: nodes) if (n.isSelected()) selected.add(n); return selected; } // Get all the edges that are selected public ArrayList selectedEdges() { ArrayList selected = new ArrayList(); for (Edge e: getEdges()) if (e.isSelected()) selected.add(e); return selected; } // Save the graph to the given file. public void saveTo(PrintWriter aFile) { aFile.println(label); // Output the nodes aFile.println(nodes.size()); for (Node n: nodes) n.saveTo(aFile); // Output the edges ArrayList edges = getEdges(); aFile.println(edges.size()); for (Edge e: edges) e.saveTo(aFile); } // Load a Graph from the given file. After the nodes and edges are loaded, // We'll have to go through and connect the nodes and edges properly. public static Graph loadFrom(BufferedReader aFile) throws IOException { // Read the label from the file and make the graph Graph aGraph = new Graph(aFile.readLine()); // Get the nodes and edges int numNodes = Integer.parseInt(aFile.readLine()); for (int i=0; i