/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: EPoint.java
* Written by: Dmitry Nadezhin, Sun Microsystems.
*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) 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.
*
* Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.database.geometry;
import java.awt.geom.Point2D;
import java.io.Serializable;
import com.sun.electric.util.math.DBMath;
import com.sun.electric.util.math.GenMath;
/**
* The <code>EPoint</code> immutable class defines a point representing
* a location in (x, y) coordinate space. This class extends abstract
* class Point2D. This class is used in Electric database.
* Coordiates are snapped to grid according to <code>DBMath.round</code> method.
*/
final public class EPoint extends Point2D implements Serializable {
/** EPoint with both zero coordinates. */
public static final EPoint ORIGIN = new EPoint(0, 0);
// ---------- Flat implementation
/**
* The X coordinate of this <code>EPoint</code> in grid unuts.
*/
private final int gridX;
/**
* The Y coordinate of this <code>EPoint</code> in grid units.
*/
private final int gridY;
/**
* The X coordinate of this <code>EPoint</code> in lambda unuts.
*/
private final double lambdaX;
/**
* The Y coordinate of this <code>EPoint</code> in lambda units.
*/
private final double lambdaY;
// ---------- ECoord implementation
// /**
// * The X coordinate of this <code>EPoint</code>.
// */
// private final ECoord x;
//
// /**
// * The Y coordinate of this <code>EPoint</code>.
// */
// private final ECoord y;
// ----------
private static int createdEPoints;
/**
* Constructs and initializes a <code>EPoint</code> with the
* specified coordinates in lambda units snapped to the grid.
* @param lambdaX the x-coordinate to which to set the newly
* constructed <code>EPoint</code> in lambda units.
* @param lambdaY the y-coordinate to which to set the newly
* constructed <code>EPoint</code> in lambda units.
*/
public EPoint(double lambdaX, double lambdaY) {
this(DBMath.lambdaToGrid(lambdaX), DBMath.lambdaToGrid(lambdaY));
}
/**
* Constructs and initializes a <code>EPoint</code> with the
* specified coordinates in grid units.
* @param gridX the x-coordinate to which to set the newly
* constructed <code>EPoint</code> in grid units.
* @param gridX the y-coordinate to which to set the newly
* constructed <code>EPoint</code> in grid units.
*/
private EPoint(long gridX, long gridY) {
// ---------- Flat implementation
this.gridX = (int)gridX;
this.gridY = (int)gridY;
if (this.gridX != gridX || this.gridY != gridY)
throw new IllegalArgumentException("Too large coordinates (" + gridX + "," + gridY + ")");
lambdaX = DBMath.gridToLambda(gridX);
lambdaY = DBMath.gridToLambda(gridY);
// ---------- ECoord implementation
// x = ECoord.fromGrid(gridX);
// y = ECoord.fromGrid(gridY);
// ----------
createdEPoints++;
}
/**
* Returns <code>EPoint</code> with specified grid coordinates.
* @param lambdaX the x-coordinate in lambda units.
* @param lambdaY the y-coordinate in lambda units.
* @return EPoint with specified grid coordinates.
*/
public static EPoint fromLambda(double lambdaX, double lambdaY) {
return lambdaX == 0 && lambdaY == 0 ? ORIGIN : fromGrid(DBMath.lambdaToGrid(lambdaX), DBMath.lambdaToGrid(lambdaY));
}
/**
* Returns <code>EPoint</code> with specified grid coordinates.
* @param gridX the x-coordinate in grid units.
* @param gridY the y-coordinate in grid units.
* @return EPoint with specified grid coordinates.
*/
public static EPoint fromGrid(long gridX, long gridY) {
return gridX == 0 && gridY == 0 ? ORIGIN : new EPoint(gridX, gridY);
}
/**
* Returns <code>EPoint</code> from specified <code>Point2D</code>
* snapped to the grid.
* @param p specified Point2D
* @return Snapped EPoint
*/
public static EPoint snap(Point2D p) {
return (p instanceof EPoint) ? (EPoint)p : fromLambda(p.getX(), p.getY());
}
/**
* Returns the X coordinate of this <code>EPoint</code>
* in lambda units in <code>double</code> precision.
* @return the X coordinate of this <code>EPoint</code>.
*/
@Override
public double getX() {
return getLambdaX();
}
/**
* Returns the Y coordinate of this <code>EPoint</code>
* in lambda unuts in <code>double</code> precision.
* @return the Y coordinate of this <code>EPoint</code>.
*/
@Override
public double getY() {
return getLambdaY();
}
/**
* Returns the X coordinate of this <code>EPoint</code>
* in lambda units in <code>double</code> precision.
* @return the X coordinate of this <code>EPoint</code>.
*/
public double getLambdaX() {
// ---------- Flat implementation
return lambdaX;
// ---------- ECoord implementation
// return x.lambdaValue();
// ----------
}
/**
* Returns the Y coordinate of this <code>EPoint</code>
* in lambda units in <code>double</code> precision.
* @return the Y coordinate of this <code>EPoint</code>.
*/
public double getLambdaY() {
// ---------- Flat implementation
return lambdaY;
// ---------- ECoord implementation
// return y.lambdaValue();
// ----------
}
/**
* Returns the X coordinate of this <code>EPoint</code>
* in grid units in <code>long</code> precision.
* @return the X coordinate of this <code>EPoint</code>.
*/
public long getGridX() {
// ---------- Flat implementation
return gridX;
// ---------- ECoord implementation
// return x.gridValue();
// ----------
}
/**
* Returns the Y coordinate of this <code>EPoint</code>
* in grid units in <code>long</code> precision.
* @return the Y coordinate of this <code>EPoint</code>.
*/
public long getGridY() {
// ---------- Flat implementation
return gridY;
// ---------- ECoord implementation
// return y.gridValue();
// ----------
}
/**
* This method overrides <code>Point2D.setLocation</code> method.
* It throws UnsupportedOperationException.
* @param x the x-coordinate to which to set this <code>EPoint</code>
* @param y the y-coordinate to which to set this <code>EPoint</code>
* @throws UnsupportedOperationException
*/
@Override
public void setLocation(double x, double y) {
throw new UnsupportedOperationException();
}
/**
* Creates mutable <code>Point2D.Double</code> from the <code>EPoint</code> in lambda units.
* @return mutable Point2D in lambda units
*/
public Point2D.Double lambdaMutable() {
return new Point2D.Double(getLambdaX(), getLambdaY());
}
/**
* Creates mutable <code>Point2D.Double</code> from the <code>EPoint</code> in grid units.
* @return mutable Point2D in grid units
*/
public Point2D.Double gridMutable() {
return new Point2D.Double(getGridX(), getGridY());
}
/**
* Returns the distance from this <code>EPoint</code> to a
* specified <code>EPoint</code> in lambda units.
* @param pt the specified <code>EPoint</code>
* @return the distance between this <code>EPoint</code> and
* the specified <code>Point</code> in lambdaUnits.
*/
public double lambdaDistance(EPoint pt) {
return DBMath.gridToLambda(gridDistance(pt));
}
/**
* Returns the distance from this <code>EPoint</code> to a
* specified <code>EPoint</code> in grid units.
* @param pt the specified <code>EPoint</code>
* @return the distance between this <code>EPoint</code> and
* the specified <code>Point</code> in gridUnits.
*/
public double gridDistance(EPoint pt) {
long PX = pt.getGridX() - this.getGridX();
long PY = pt.getGridY() - this.getGridY();
return PY == 0 ? Math.abs(PX) : PX == 0 ? Math.abs(PY) : Math.hypot(PX, PY);
}
/**
* Returns true if both coordinates of this EPoint are "small ints".
* @return true if both coordinates of this EPoint are "small ints".
* @see com.sun.electric.util.math.GenMath#MIN_SMALL_COORD
* @see com.sun.electric.util.math.GenMath#MAX_SMALL_COORD
*/
public boolean isSmall() {
// ---------- Flat implementation
return (((gridX - GenMath.MIN_SMALL_COORD) | (gridY - GenMath.MIN_SMALL_COORD)) & Integer.MIN_VALUE) == 0;
// ---------- ECoord implementation
// return x.isSmall() & y.isSmall()
// ----------
}
/**
* Returns true if this EPoint is equal to the other EPoint.
* This method returns the same result as general <code>equals</code>,
* but it could be a little faster, because no virtual method dispatching is required.
* @return true if this EPoint is equal to the other EPoint.
* @see java.awt.geom.Point2D#equals
*/
public boolean equals(EPoint that) {
return this.gridX == that.gridX && this.gridY == that.gridY;
}
/**
* Returns a <code>String</code> that represents the value
* of this <code>EPoint</code>.
* @return a string representation of this <code>EPoint</code>.
*/
public String toString() {
return "EPoint["+getX()+", "+getY()+"]";
}
/**
* Prints statistics about EPoint objects.
*/
public static void printStatistics() {
System.out.println(createdEPoints + " EPoints created");
// ---------- ECoord implementation
// ECoord.printStatistics();
// ----------
}
}