Package org.graphstream.ui.swingViewer.basicRenderer.shapes

Source Code of org.graphstream.ui.swingViewer.basicRenderer.shapes.Arrow

/*
* Copyright 2006 - 2013
*     Stefan Balev     <stefan.balev@graphstream-project.org>
*     Julien Baudry    <julien.baudry@graphstream-project.org>
*     Antoine Dutot    <antoine.dutot@graphstream-project.org>
*     Yoann Pigné      <yoann.pigne@graphstream-project.org>
*     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
*
* This file is part of GraphStream <http://graphstream-project.org>.
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can  use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.ui.swingViewer.basicRenderer.shapes;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;

import org.graphstream.ui.graphicGraph.GraphicEdge;
import org.graphstream.ui.graphicGraph.GraphicNode;
import org.graphstream.ui.graphicGraph.StyleGroup;
import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.StrokeMode;
import org.graphstream.ui.swingViewer.util.GraphMetrics;

public class Arrow extends Shape {
  protected Color fillColor = Color.BLACK;

  protected Color strokeColor = Color.BLACK;

  protected int lengthGu = 0;

  protected int widthGu = 0;

  protected double x, y;

  protected Path2D.Float path = new Path2D.Float();

  public void setArrowLengthGu(int lengthGu) {
    this.lengthGu = lengthGu;
  }

  public void setArrowWidthGu(int widthGu) {
    this.widthGu = widthGu;
  }

  public void setFillColor(Color color) {
    fillColor = color;
  }

  public void setStrokeColor(Color color) {
    strokeColor = color;
  }

  @Override
  public void renderFill(Graphics2D g, GraphMetrics metrics) {
    g.setColor(fillColor);
    g.fill(path);
  }

  @Override
  public void renderStroke(Graphics2D g, GraphMetrics metrics) {
    g.setColor(strokeColor);
    g.draw(path);
  }

  // Utility

  protected void setPositionAndShape(GraphicEdge edge, GraphMetrics metrics) {
    // Compute the direction vector and some lengths.

    x = edge.to.x;
    y = edge.to.y;
    double vx = x - edge.from.x;
    double vy = y - edge.from.y;
    double off = evalTargetRadius(edge, metrics);

    // Normalise the vectors.

    double d = (double) Math.sqrt(vx * vx + vy * vy);

    vx /= d;
    vy /= d;

    // Choose an arrow "length".

    x -= vx * off;
    y -= vy * off;

    setShapeAt(x, y, vx, vy);
  }

  /**
   * Compute the shape of the arrow.
   *
   * @param x
   *            Point at which the edge crosses the node shape.
   * @param y
   *            Point at which the edge crosses the node shape.
   * @param dx
   *            The arrow vector (and length).
   * @param dy
   *            The arrow vector (and length).
   */
  protected void setShapeAt(double x, double y, double dx, double dy) {
    // Compute the edge vector (1) and the perpendicular vector (2).

    double dx2 = dy;
    double dy2 = -dx;

    // Normalise the vectors.

    double d2 = (double) Math.sqrt(dx2 * dx2 + dy2 * dy2);

    dx2 /= d2;
    dy2 /= d2;

    // Choose an arrow "width".

    dx2 *= widthGu;
    dy2 *= widthGu;

    // Create a polygon.

    path.reset();
    path.moveTo(x, y);
    path.lineTo(x - dx + dx2, y - dy + dy2);
    path.lineTo(x - dx - dx2, y - dy - dy2);
    path.closePath();
  }

  /**
   * Evaluate the position of the arrow to avoid putting it above or under the
   * target node.
   *
   * @param edge
   *            The edge.
   * @param metrics
   *            The metrics.
   * @return The length from the node centre along the edge to position the
   *         arrow.
   */
  protected double evalTargetRadius(GraphicEdge edge, GraphMetrics metrics) {
    GraphicNode target = edge.to;
    StyleGroup group = target.getStyle();
    double w = metrics.lengthToGu(group.getSize(), 0);
    double h = group.getSize().size() > 1 ? metrics.lengthToGu(
        group.getSize(), 1) : w;

    if (w == h) {
      double b = group.getStrokeMode() != StrokeMode.NONE ? metrics
          .lengthToGu(group.getStrokeWidth()) : 0;
      return ((w / 2) + b);
    } else {
      return evalEllipseRadius(edge, w, h);
    }
  }

  /**
   * Compute the length of a vector along the edge from the ellipse centre to
   * the intersection between the edge and the ellipse.
   *
   * @param edge
   *            The edge representing the vector.
   * @param w
   *            The ellipse first radius (width/2).
   * @param h
   *            The ellipse second radius (height/2).
   * @return The length of the radius along the edge vector.
   */
  protected double evalEllipseRadius(GraphicEdge edge, double w, double h) {
    // Vector of the entering edge.

    double dx;
    double dy;

    dx = edge.to.x - edge.from.x;
    dy = edge.to.y - edge.from.y;

    // The entering edge must be deformed by the ellipse ratio to find the
    // correct angle.

    dy *= (w / h); // I searched a lot to find this line was missing ! Tsu !
            // This comment is in memory of this long search.

    // Find the angle of the entering vector with (1,0).

    double d = (double) Math.sqrt(dx * dx + dy * dy);
    double a = dx / d;

    // Compute the coordinates at which the entering vector and the ellipse
    // cross.

    a = (double) Math.acos(a);
    dx = (double) Math.cos(a) * w;
    dy = (double) Math.sin(a) * h;

    // The distance from the ellipse centre to the crossing point of the
    // ellipse and
    // vector. Yo !

    return Math.sqrt(dx * dx + dy * dy);
  }
TOP

Related Classes of org.graphstream.ui.swingViewer.basicRenderer.shapes.Arrow

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.