/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. S�nchez (luciano@uniovi.es) J. Alcal�-Fdez (jalcala@decsai.ugr.es) S. Garc�a (sglopez@ujaen.es) A. Fern�ndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) This program 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. This program 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 this program. If not, see http://www.gnu.org/licenses/ **********************************************************************/ /** * * File: Arc.java * * A class representing arcs of the graph * * @author Written by Admin 4/8/2010 * @version 1.0 * @since JDK1.5 */ package keel.GraphInterKeel.experiments; import java.awt.*; import java.awt.geom.*; import java.io.*; public class Arc implements Serializable { private int sourceNode; private int destinationNode; private transient Shape line; private transient Image myImage; private transient GraphPanel pd; /** * Builder */ public Arc() { } /** * Builder * @param p Parent graph */ public Arc(GraphPanel p) { myImage = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/keel/GraphInterKeel/resources/ico/experiments/flecha.gif")); pd = p; } /** * Builder * @param source Source node * @param destination Destination node * @param p Parent graph */ public Arc(int source, int destination, GraphPanel p) { sourceNode = source; destinationNode = destination; pd = p; myImage = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/keel/GraphInterKeel/resources/ico/experiments/flecha.gif")); } /** * Gets the source node of this arc * @return The source node */ public int getSource() { return sourceNode; } /** * Gets the destination node * @return the destination node */ public int getDestination() { return destinationNode; } /** * Sets the node source * @param source The new node source */ public void setSource(int source) { sourceNode = source; pd.mainGraph.setModified(true); } /** * Sets the destination node * @param destination the new destination node */ public void setDestination(int destination) { destinationNode = destination; pd.mainGraph.setModified(true); } /** * Gets the source node of this arc * @return The source node */ public int getSource2() { return sourceNode; } /** * Gets the destination node * @return the destination node */ public int getDestination2() { return destinationNode; } /** * Sets the node source * @param source The new node source */ public void setSource2(int source) { sourceNode = source; } /** * Sets the destination node * @param destination the new destination node */ public void setDestination2(int destination) { destinationNode = destination; } /** * Draws this component * @param g2 The graphic element * @param source The point of origin * @param destination The destination point * @param select if this element is selected */ public void draw(Graphics2D g2, Point source, Point destination, boolean select) { Point intersect = intersection(source, destination); destination = intersect; line = new Line2D.Float(source, destination); if (select) { Stroke s = g2.getStroke(); g2.setStroke(new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{1, 1}, 0)); g2.draw(line); g2.setStroke(s); } else { g2.draw(line); } AffineTransform af = g2.getTransform(); double angulo = Math.atan2(destination.y - source.y, destination.x - source.x) - (5 * Math.PI / 4); g2.rotate(angulo, intersect.x, intersect.y); g2.drawImage(myImage, intersect.x, intersect.y, 15, 15, pd); g2.setTransform(af); } /** * Test if the provided point is inside * @param point Point * @param source Source node * @param destination Destination node * @return If the provided point is inside */ public boolean isInside(Point point, Point source, Point destination) { double dist = ((Line2D) line).ptSegDist(point); if (dist < 10) { return true; } else { return false; } } /** * Computes the intersection of two nodes * @param source Source node * @param destination Destination node * @return Intersection of two nodes as a point */ private Point intersection(Point source, Point destination) { Point punto = new Point(); Point p0, p1, p2, p3; double t, d; double angulo = Math.atan2(destination.y - source.y, destination.x - source.x) * 180.0 / Math.PI; if (angulo < 0) { angulo += 360; } if (angulo >= 45.0 && angulo < 135) { p0 = new Point(destination.x - 25, destination.y - 25); p1 = new Point(destination.x + 25, destination.y - 25); } else if (angulo >= 135.0 && angulo < 225) { p0 = new Point(destination.x + 25, destination.y - 25); p1 = new Point(destination.x + 25, destination.y + 25); } else if (angulo >= 225.0 && angulo < 315) { p0 = new Point(destination.x + 25, destination.y + 25); p1 = new Point(destination.x - 25, destination.y + 25); } else { p0 = new Point(destination.x - 25, destination.y + 25); p1 = new Point(destination.x - 25, destination.y - 25); } p2 = source; p3 = destination; d = p0.x * (p3.y - p2.y) + p1.x * (p2.y - p3.y) + p3.x * (p1.y - p0.y) + p2.x * (p0.y - p1.y); t = p0.x * (p3.y - p2.y) + p2.x * (p0.y - p3.y) + p3.x * (p2.y - p0.y); if (d != 0) { t = t / d; } punto.x = (int) (p0.x + (p1.x - p0.x) * t); punto.y = (int) (p0.y + (p1.y - p0.y) * t); return punto; } }