/*
* Copyright (C) 2012 Addition, Lda. (addition at addition dot pt)
*
* 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/.
*/
package org.addition.epanet.ui;
import org.addition.epanet.network.Network;
import org.addition.epanet.network.structures.*;
import org.addition.epanet.network.structures.Label;
import org.addition.epanet.network.structures.Point;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.*;
import java.util.List;
/**
* Network 2D rendering class for the EpanetUI class.
*/
public class NetworkImage {
static private Color TANKS_FILL_COLOR = new Color(0xcccccc);
static private Color TANKS_STROKE_COLOR = new Color(0x666666);
static private int TANK_DIAM = 10;
static private Color RESERVOIRS_FILL_COLOR = new Color(0x666666);
static private Color RESERVOIRS_STROKE_COLOR = new Color(0xcccccc);
static private int RESERVOIR_DIAM = 10;
private static final Color PIPES_FILL_COLOR = new Color(0x666666);
private static final Color NODE_STROKE_COLOR = new Color(0, 0, 0, .5f);
private static final Color NODE_FILL_COLOR = new Color(0xcc / 256f, 0xcc / 256f, 0xcc / 256f, .4f);
private static final int NODE_DIAM = 2;
static private Color LABEL_COLOR = new Color(0,0,0);
/**
* Get the nearest node to the mouse cursor position.
* @param w Canvas width.
* @param h Canvas height.
* @param x Mouse x position.
* @param y Mouse y position.
* @param net Epanet network.
* @return Reference to the nearest node.
*/
public static Node peekNearest(int w, int h,int x,int y, Network net){
if(net==null)
return null;
Rectangle2D.Double bounds = null;
for(Node node : net.getNodes()){
if (node.getPosition() != null) {
if (bounds == null)
bounds = new Rectangle2D.Double((int) node.getPosition().getX(), (int) -node.getPosition().getY(), 0, 0);
else
bounds.add(new java.awt.Point((int) node.getPosition().getX(), (int) -node.getPosition().getY()));
}
}
for(Link link : net.getLinks()){
//java.util.List<org.addition.epanetold.Types.Point> vertices = link.getVertices();
for (Point position : link.getVertices()) {
if (position != null) {
if (bounds == null)
bounds = new Rectangle2D.Double((int) position.getX(), (int) -position.getY(), 0, 0);
else
bounds.add(new java.awt.Point((int) position.getX(), (int) -position.getY()));
}
}
}
double factor = (bounds.width / bounds.height) < (((double) w) / h) ? h / bounds.height : w / bounds.width;
double dx = bounds.getMinX();
double dy = bounds.getMinY();
double dwidth = Math.abs(bounds.getMaxX() - bounds.getMinX());
double dheight = Math.abs(bounds.getMaxY() - bounds.getMinY());
factor *= .9d;
dx += dwidth * .5d - w * 0.5 / factor;
dy += dheight * .5d - h * 0.5 / factor;
Node nearest = null;
double distance = 0;
for(Node n : net.getNodes()){
Point point = new Point(
(int) ((n.getPosition().getX() - dx) * factor),
(int) ((-n.getPosition().getY() - dy) * factor));
double dist = Math.sqrt( Math.pow(point.getX() - x,2) + Math.pow(point.getY() - y,2));
if(nearest == null || dist< distance){
nearest = n;
distance = dist;
}
}
return nearest;
}
/**
* Render the network in the canvas.
* @param g Reference to the canvas graphics.
* @param w Canvas width.
* @param h Canvas height.
* @param net Epanet network.
* @param drawPipes Draw pipes flag.
* @param drawTanks Draw tanks flag.
* @param drawNodes Draw nodes flag.
* @param selNode Reference to the selected node.
*/
public static void drawNetwork(Graphics g, int w, int h, Network net, boolean drawPipes, boolean drawTanks, boolean drawNodes, Node selNode) {
//int maxNodes = net.getMaxNodes();
//int maxLinks = net.getMaxLinks();
Rectangle2D.Double bounds = null;
for(Node node : net.getNodes()){
if (node.getPosition() != null) {
if (bounds == null)
bounds = new Rectangle2D.Double((int) node.getPosition().getX(), (int) -node.getPosition().getY(), 0, 0);
else
bounds.add(new java.awt.Point((int) node.getPosition().getX(), (int) -node.getPosition().getY()));
}
}
for(Link link : net.getLinks()){
//java.util.List<org.addition.epanetold.Types.Point> vertices = link.getVertices();
for (Point position : link.getVertices()) {
if (position != null) {
if (bounds == null)
bounds = new Rectangle2D.Double((int) position.getX(), (int) -position.getY(), 0, 0);
else
bounds.add(new java.awt.Point((int) position.getX(), (int) -position.getY()));
}
}
}
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g.setColor(new Color(0x99, 0x99, 0x99));
//g.drawRect(0, 0, w - 1, h - 1);
double factor = (bounds.width / bounds.height) < (((double) w) / h) ? h / bounds.height : w / bounds.width;
double dx = bounds.getMinX();
double dy = bounds.getMinY();
double dwidth = Math.abs(bounds.getMaxX() - bounds.getMinX());
double dheight = Math.abs(bounds.getMaxY() - bounds.getMinY());
factor *= .9d;
dx += dwidth * .5d - w * 0.5 / factor;
dy += dheight * .5d - h * 0.5 / factor;
//tanks
if (drawTanks) {
for(Tank tank : net.getTanks()){
if(tank.getArea()==0){
// Reservoir
Point position = tank.getPosition();
if (position != null) {
Point point = new Point(
(int) ((position.getX() - dx) * factor),
(int) ((-position.getY() - dy) * factor));
g.setColor(RESERVOIRS_FILL_COLOR);
g.fillRect((int)(point.getX() - RESERVOIR_DIAM / 2),(int)(point.getY()-RESERVOIR_DIAM/2), RESERVOIR_DIAM, RESERVOIR_DIAM);
g.setColor(RESERVOIRS_STROKE_COLOR);
g.drawRect((int)(point.getX() - RESERVOIR_DIAM / 2),(int)(point.getY()-RESERVOIR_DIAM/2), RESERVOIR_DIAM, RESERVOIR_DIAM);
}
}
else {
// Tank
Point position = tank.getPosition();
if (position != null) {
Point point = new Point(
(int) ((position.getX() - dx) * factor),
(int) ((-position.getY() - dy) * factor));
g.setColor(TANKS_FILL_COLOR);
g.fillRect((int)(point.getX() - RESERVOIR_DIAM / 2),(int)(point.getY()-RESERVOIR_DIAM/2), TANK_DIAM, TANK_DIAM);
g.setColor(TANKS_STROKE_COLOR);
g.drawRect((int)(point.getX() - RESERVOIR_DIAM / 2),(int)(point.getY()-RESERVOIR_DIAM/2), TANK_DIAM, TANK_DIAM);
}
}
}
}
if (drawPipes) {
//links
g.setColor(PIPES_FILL_COLOR);
for(Link link : net.getLinks()){
List<Point> vertices = new ArrayList<Point>(link.getVertices());
Node node1 = link.getFirst();
Node node2 = link.getSecond();
vertices.add(0, node1.getPosition());
vertices.add(node2.getPosition());
Point prev = null;
for (Point position : vertices) {
Point point = new Point(
(int) ((position.getX() - dx) * factor),
(int) ((-position.getY() - dy) * factor));
if (prev != null) {
g.drawLine((int)prev.getX(),(int) prev.getY(),(int) point.getX(),(int) point.getY());
}
prev = point;
}
}
}
if (drawNodes) {
//nodes
Color nodefillColor = NODE_FILL_COLOR;
Color nodeStrokeColor = NODE_STROKE_COLOR;
g.setColor(nodefillColor);
for(Node node : net.getNodes()){
Point position = node.getPosition();
if (position != null) {
Point point = new Point(
(int) ((position.getX() - dx) * factor),
(int) ((-position.getY() - dy) * factor));
g.setColor(nodefillColor);
g.fillOval((int)(point.getX() - NODE_DIAM / 2), (int)(point.getY() - NODE_DIAM / 2), NODE_DIAM, NODE_DIAM);
g.setColor(nodeStrokeColor);
g.drawOval((int)(point.getX() - NODE_DIAM / 2), (int)(point.getY() - NODE_DIAM / 2), NODE_DIAM, NODE_DIAM);
}
}
}
for(Label l : net.getLabels()){
Point point = new Point(
(int) ((l.getPosition().getX() - dx) * factor),
(int) ((-l.getPosition().getY() - dy) * factor));
g.setColor(LABEL_COLOR);
g.drawString(l.getText(),(int)point.getX(),(int)point.getY());
}
if(selNode!=null){
Point point = new Point(
(int) ((selNode.getPosition().getX() - dx) * factor),
(int) ((-selNode.getPosition().getY() - dy) * factor));
g.setColor(new Color(0xFF0000));
g.drawOval((int)(point.getX() - 20 / 2), (int)(point.getY() - 20 / 2), 20, 20);
g.setColor(LABEL_COLOR);
g.drawString(selNode.getId(),(int)point.getX()+20,(int)point.getY()+20);
}
}
}