原文链接
package cma. common. isoline ;
import java. awt. Color ;
import java. awt. Font ;
import java. awt. Graphics2D ;
import java. awt. Point ;
import java. awt. geom. Point2D ;
public abstract class Coordinate {
public static int LAMBERT = 1 ;
public static int MERCATOR = 2 ;
public static int BBQ = 3 ;
public static int NBQ = 4 ;
public static int LINEAR = 5 ;
public static int POLAR = 6 ;
public static double RADIUS = 6371.004 ;
public static double RADIUS_POLAR = 6356.755 ;
public static double RADIUS_EQUATOR = 6373.140 ;
protected Point2D. Double standard;
protected Point2D. Double center;
protected Point place;
protected Point offset;
protected Point2D. Double scaleXY;
protected double scale;
protected double scaleOriginal;
public int type = - 1 ;
public Point2D. Double getStandard ( ) {
return ( standard ) ;
}
public Point2D. Double getCenter ( ) {
return ( center ) ;
}
public Point getPlace ( ) {
return ( place ) ;
}
public double getScale ( ) {
return ( scale ) ;
}
public Point2D. Double getScaleXY ( ) {
return ( scaleXY ) ;
}
public void zoomIn ( ) {
scale = scale * 2.0 ;
}
public void zoomOut ( ) {
scale = scale / 2.0 ;
}
public void revert ( ) {
scale = scaleOriginal;
}
public abstract Point getPosition ( double lon, double lat ) ;
public abstract Point2D. Double getCoordinate ( int x, int y ) ;
public double getAngle ( double lon, double lat ) {
return ( 0.0 ) ;
}
public abstract void drawGridLine ( Graphics2D g, Font f, Color c, int inc_lon, int inc_lat ) ;
}
package cma. common. isoline ;
import java. awt. Color ;
import java. awt. Font ;
import java. awt. FontMetrics ;
import java. awt. Graphics2D ;
import java. awt. Point ;
import java. awt. geom. Point2D ;
import java. text. DecimalFormat ;
public class Linear extends Coordinate {
public void reset ( double lon, double lat, int px, int py, double sc, double sx, double sy ) {
type = Coordinate . LINEAR;
center = new Point2D. Double (
lon < 0.0 ? 0.0 : lon > 360.0 ? 360.0 : lon,
lat < - 90.0 ? - 90.0 : lat > 90.0 ? 90.0 : lat
) ;
place = new Point ( px, py ) ;
scaleXY = new Point2D. Double ( sx== 0.0 ? 1.0 : Math . abs ( sx ) , sy== 0.0 ? 1.0 : Math . abs ( sy ) ) ;
scale = Math . abs ( sc ) ;
scaleOriginal = scale;
offset = new Point ( 0 , 0 ) ;
}
public Linear ( ) {
reset ( 109.40 , 24.35 , 640 , 480 , 1.0 , 10.0 , 10.0 ) ;
}
public Linear ( double lon, double lat, int px, int py, double sc ) {
reset ( lon, lat, px, py, sc, 10.0 * sc, 10.0 * sc ) ;
}
public Linear ( double lon, double lat, int px, int py, double sx, double sy ) {
reset ( lon, lat, px, py, 1.0 , sx, sy ) ;
}
public void reset ( double lon, double lat, int px, int py, double sx, double sy ) {
reset ( lon, lat, px, py, 1.0 , sx, sy ) ;
}
public Point getPosition ( double lon, double lat ) {
return (
new Point (
place. x + ( int ) ( 0.5 + ( lon - center. x ) * scale * scaleXY. x ) ,
place. y + ( int ) ( 0.5 + ( center. y - lat ) * scale * scaleXY. y )
)
) ;
}
public Point2D. Double getCoordinate ( int x, int y ) {
return (
new Point2D. Double (
center. x + ( x - place. x ) / scale / scaleXY. x,
center. y + ( place. y - y ) / scale / scaleXY. y
)
) ;
}
public void drawGridLine ( Graphics2D g, Font f, Color c, int inc_lon, int inc_lat ) {
DecimalFormat df = new DecimalFormat ( "0.#" ) ;
Color saveColor = g. getColor ( ) ;
Font saveFont = g. getFont ( ) ;
g. setColor ( c ) ;
g. setFont ( null == f? f: new Font ( "Times New Roman" , Font . PLAIN, 12 ) ) ;
FontMetrics fm = g. getFontMetrics ( ) ;
String text;
byte tmpByte [ ] ;
int bytesWidth, bytesHeight = fm. getHeight ( ) ; ;
Point pos1, pos2;
if ( inc_lon > 0 ) {
for ( double lon= 0.0 ; lon<= 360.0 ; lon= lon+ inc_lon ) {
if ( 180.0 == lon ) {
for ( double lat= - 90.0 ; lat<= 90.0 ; lat= lat+ inc_lat ) {
text = df. format ( lat ) ;
tmpByte = text. getBytes ( ) ;
bytesWidth = fm. bytesWidth ( tmpByte, 0 , tmpByte. length ) ;
pos1 = this . getPosition ( lon, lat ) ;
g. drawString ( text, pos1. x- bytesWidth/ 2 , pos1. y+ bytesHeight/ 3 ) ;
}
}
pos1 = this . getPosition ( lon, - 90.0 ) ;
pos2 = this . getPosition ( lon, 90.0 ) ;
g. drawLine ( pos1. x, pos1. y, pos2. x, pos2. y ) ;
}
}
if ( inc_lat > 0 ) {
for ( double lat= - 90.0 ; lat<= 90.0 ; lat= lat+ inc_lat ) {
if ( 0.0 == lat ) {
for ( double lon= 0.0 ; lon<= 360.0 ; lon= lon+ inc_lon ) {
text = df. format ( lon ) ;
tmpByte = text. getBytes ( ) ;
bytesWidth = fm. bytesWidth ( tmpByte, 0 , tmpByte. length ) ;
pos1 = this . getPosition ( lon, lat ) ;
g. drawString ( text, pos1. x- bytesWidth/ 2 , pos1. y+ bytesHeight/ 3 ) ;
}
}
pos1 = this . getPosition ( 0.0 , lat ) ;
pos2 = this . getPosition ( 360.0 , lat ) ;
g. drawLine ( pos1. x, pos1. y, pos2. x, pos2. y ) ;
}
}
g. setFont ( saveFont ) ;
g. setColor ( saveColor ) ;
}
}
package cma. common. isoline ;
public class TriangleVertex {
public int A ;
public int B ;
public int C ;
public boolean reset ( int i, int j, int k ) {
if ( i< 0 || j< 0 || k< 0 ||
i== j|| j== k|| k== i ) {
A = - 1 ;
B = - 1 ;
C = - 1 ;
return ( false ) ;
}
else {
A = Math . min ( Math . min ( i, j ) , k ) ;
C = Math . max ( Math . max ( i, j ) , k ) ;
B =
i!= A && i!= C ? i:
j!= A && j!= C ? j:
k;
return ( true ) ;
}
}
public TriangleVertex ( ) {
A = - 1 ;
B = - 1 ;
C = - 1 ;
}
public TriangleVertex ( int i, int j, int k ) {
reset ( i, j, k ) ;
}
public boolean equals ( int a, int b, int c ) {
return ( exists ( a, b, c ) ) ;
}
public boolean exists ( int a, int b, int c ) {
return (
a!= b&& b!= c&& c!= a&&
exists ( a ) &&
exists ( b ) &&
exists ( c )
) ;
}
public boolean exists ( int a, int b ) {
return ( a!= b&& exists ( a ) && exists ( b ) ) ;
}
public boolean exists ( int a ) {
return (
a>= 0 && ( a== A || a== B || a== C )
) ;
}
}
package cma. common. isoline ;
import java. awt. Color ;
import java. awt. Graphics2D ;
import java. awt. Point ;
import java. awt. geom. Point2D ;
import java. awt. image. BufferedImage ;
import java. io. File ;
import java. util. Arrays ;
import java. util. Vector ;
import javax. imageio. ImageIO ;
public class Delaunay {
public Point2D. Double [ ] points;
public Vector triangle;
public Vector circle;
public Vector radius;
private int nt;
private int np;
public Delaunay ( Point2D. Double [ ] pts) {
np = pts. length;
points = new Point2D. Double [ np + 3 ] ;
for ( int i = 0 ; i < np; i++ ) {
points[ i] = new Point2D. Double ( pts[ i] . x, pts[ i] . y) ;
}
triangle = new Vector ( ) ;
circle = new Vector ( ) ;
radius = new Vector ( ) ;
nt = 0 ;
}
private boolean createEdge ( ) {
double dmax, xmin, ymin, xmax, ymax, xmid, ymid;
xmin = points[ 0 ] . x;
ymin = points[ 0 ] . y;
xmax = points[ 0 ] . x;
ymax = points[ 0 ] . y;
for ( int i = 1 ; i < np; i++ ) {
xmin = Math . min ( xmin, points[ i] . x) ;
ymin = Math . min ( ymin, points[ i] . y) ;
xmax = Math . max ( xmax, points[ i] . x) ;
ymax = Math . max ( ymax, points[ i] . y) ;
}
xmin = Math . floor ( xmin) ;
xmax = Math . ceil ( xmax) ;
ymin = Math . floor ( ymin) ;
ymax = Math . ceil ( ymax) ;
xmid = ( xmin + xmax) / 2.0 ;
ymid = ( ymin + ymax) / 2.0 ;
dmax = Math . max ( xmax - xmin, ymax - ymin) ;
dmax = Math . ceil ( 1.1 * dmax) ;
points[ np + 0 ] = new Point2D. Double ( xmid - dmax, ymid - dmax / 2 ) ;
points[ np + 1 ] = new Point2D. Double ( xmid, ymid + dmax / 2 + dmax) ;
points[ np + 2 ] = new Point2D. Double ( xmid + dmax, ymid - dmax / 2 ) ;
boolean enabled = add ( np + 0 , np + 1 , np + 2 ) ;
return ( enabled) ;
}
private void deleteEdge ( ) {
int sA = np + 0 ;
int sB = np + 1 ;
int sC = np + 2 ;
TriangleVertex tv;
for ( int i = nt - 1 ; i >= 0 ; i-- ) {
tv = ( TriangleVertex ) triangle. get ( i) ;
if ( tv. exists ( sA) || tv. exists ( sB) || tv. exists ( sC) ) {
this . delete ( i) ;
}
}
}
public Point2D. Double circumcircle ( double x1, double y1, double x2, double y2, double x3, double y3) {
double x1x1 = x1 * x1;
double x2x2 = x2 * x2;
double x3x3 = x3 * x3;
double y1y1 = y1 * y1;
double y2y2 = y2 * y2;
double y3y3 = y3 * y3;
double x2_x1 = x2 - x1;
double x3_x1 = x3 - x1;
double y2_y1 = y2 - y1;
double y3_y1 = y3 - y1;
double x = ( ( y2_y1) * ( y3y3 - y1y1 + x3x3 - x1x1) - ( y3_y1) * ( y2y2 - y1y1 + x2x2 - x1x1) )
/ ( 2 * ( x3_x1) * ( y2_y1) - 2 * ( x2_x1) * ( y3_y1) ) ;
double y = ( ( x2_x1) * ( x3x3 - x1x1 + y3y3 - y1y1) - ( x3_x1) * ( x2x2 - x1x1 + y2y2 - y1y1) )
/ ( 2 * ( y3_y1) * ( x2_x1) - 2 * ( y2_y1) * ( x3_x1) ) ;
return ( new Point2D. Double ( x, y) ) ;
}
public int position ( double x0, double y0, double x1, double y1, double x2, double y2) {
double xab = ( x0 - x1) * ( y2 - y1) - ( y0 - y1) * ( x2 - x1) ;
return ( xab < 0.0 ? - 1 : xab == 0.0 ? 0 : 1 ) ;
}
public boolean cross ( double xa, double ya, double xb, double yb, double xc, double yc, double xd, double yd) {
int a_cd = this . position ( xa, ya, xc, yc, xd, yd) ;
int b_cd = this . position ( xb, yb, xc, yc, xd, yd) ;
return ( 1 != a_cd * b_cd) ;
}
private int [ ] contains ( Point2D. Double p) {
if ( nt == 0 ) {
return ( null ) ;
}
Vector lists = new Vector ( ) ;
Point2D. Double pc;
double r;
double pr2;
int [ ] res = new int [ nt] ;
int count = 0 ;
Arrays . fill ( res, - 1 ) ;
for ( int i = 1 ; i < nt; i++ ) {
r = ( ( Double ) radius. get ( i) ) . doubleValue ( ) ;
pc = ( Point2D. Double ) circle. get ( i) ;
pr2 = ( p. x - pc. x) * ( p. x - pc. x) + ( p. y - pc. y) * ( p. y - pc. y) ;
if ( pr2 <= r * r) {
res[ count++ ] = i;
}
}
if ( count == 0 ) {
return ( null ) ;
}
int [ ] results = new int [ count] ;
for ( int i = 0 ; i < count; i++ ) {
results[ i] = res[ i] ;
}
return ( results) ;
}
public void clear ( ) {
triangle. clear ( ) ;
circle. clear ( ) ;
radius. clear ( ) ;
nt = 0 ;
}
public void remove ( int index) {
if ( index > 0 && index < nt) {
delete ( index) ;
}
}
private void delete ( int index) {
if ( index >= 0 && index < nt) {
TriangleVertex tv = ( TriangleVertex ) triangle. get ( index) ;
triangle. remove ( index) ;
circle. remove ( index) ;
radius. remove ( index) ;
nt-- ;
}
}
public void remove ( int [ ] index) {
if ( null == index || index. length == 0 ) {
return ;
}
int [ ] idx = new int [ index. length] ;
for ( int i = 0 ; i < index. length; i++ ) {
idx[ i] = index[ i] ;
}
Arrays . sort ( idx) ;
for ( int i = idx. length - 1 ; i >= 0 ; i-- ) {
this . remove ( idx[ i] ) ;
}
}
public boolean add ( int index, TriangleVertex abc) {
int posAB = this . position ( points[ index] . x, points[ index] . y, points[ abc. A] . x, points[ abc. A] . y, points[ abc. B] . x,
points[ abc. B] . y) ;
int posBC = this . position ( points[ index] . x, points[ index] . y, points[ abc. B] . x, points[ abc. B] . y, points[ abc. C] . x,
points[ abc. C] . y) ;
int posCA = this . position ( points[ index] . x, points[ index] . y, points[ abc. C] . x, points[ abc. C] . y, points[ abc. A] . x,
points[ abc. A] . y) ;
boolean inTriangle =
( posAB == - 1 && posBC == - 1 && posCA == - 1 ) || ( posAB == 1 && posBC == 1 && posCA == 1 ) ;
boolean enabled = false ;
if ( inTriangle) {
enabled = this . add ( index, abc. A, abc. B) && this . add ( index, abc. B, abc. C) && this . add ( index, abc. C, abc. A) ;
} else if ( posBC == posCA) {
enabled = this . add ( index, abc. A, abc. B) ;
} else if ( posAB == posCA) {
enabled = this . add ( index, abc. B, abc. C) ;
} else if ( posAB == posBC) {
enabled = this . add ( index, abc. C, abc. A) ;
} else {
enabled = false ;
}
return ( enabled) ;
}
public boolean add ( int a, int b, int c) {
boolean enabled = false ;
TriangleVertex tv = new TriangleVertex ( ) ;
enabled = tv. reset ( a, b, c) ;
if ( ! enabled) {
return ( false ) ;
}
int ntSave = nt;
try {
triangle. add ( tv) ;
Point2D. Double p = this . circumcircle ( points[ a] . x, points[ a] . y, points[ b] . x, points[ b] . y, points[ c] . x,
points[ c] . y) ;
circle. add ( p) ;
Double d = new Double (
Math . sqrt ( ( points[ a] . x - p. x) * ( points[ a] . x - p. x) + ( points[ a] . y - p. y) * ( points[ a] . y - p. y) ) ) ;
radius. add ( d) ;
nt++ ;
return ( true ) ;
} catch ( Exception ex) {
for ( int i = triangle. size ( ) - 1 ; i > ntSave; i-- ) {
triangle. remove ( i) ;
}
for ( int i = circle. size ( ) - 1 ; i > ntSave; i-- ) {
circle. remove ( i) ;
}
for ( int i = radius. size ( ) - 1 ; i > ntSave; i-- ) {
radius. remove ( i) ;
}
nt = ntSave;
System . out. println ( ex. getMessage ( ) ) ;
ex. printStackTrace ( ) ;
return ( false ) ;
}
}
public void add ( int index, int [ ] lists) {
if ( null == lists) {
return ;
}
int [ ] idx = new int [ lists. length] ;
for ( int i = 0 ; i < lists. length; i++ ) {
idx[ i] = lists[ i] ;
}
Arrays . sort ( idx) ;
TriangleVertex [ ] tvs = new TriangleVertex [ idx. length] ;
boolean [ ] [ ] existsSize = new boolean [ 3 ] [ idx. length] ;
Arrays . fill ( existsSize[ 0 ] , false ) ;
Arrays . fill ( existsSize[ 1 ] , false ) ;
Arrays . fill ( existsSize[ 2 ] , false ) ;
for ( int i = 0 ; i < idx. length; i++ ) {
tvs[ i] = ( TriangleVertex ) triangle. get ( idx[ i] ) ;
}
for ( int i = 0 ; i < tvs. length; i++ ) {
for ( int j = 0 ; j < tvs. length; j++ ) {
if ( i != j) {
existsSize[ 0 ] [ i] = existsSize[ 0 ] [ i] || tvs[ j] . exists ( tvs[ i] . A, tvs[ i] . B) ;
existsSize[ 1 ] [ i] = existsSize[ 1 ] [ i] || tvs[ j] . exists ( tvs[ i] . B, tvs[ i] . C) ;
existsSize[ 2 ] [ i] = existsSize[ 2 ] [ i] || tvs[ j] . exists ( tvs[ i] . C, tvs[ i] . A) ;
}
}
}
int pos1, pos2;
for ( int i = 0 ; i < tvs. length; i++ ) {
if ( ! existsSize[ 0 ] [ i] &&
! this . cross (
points[ index] . x, points[ index] . y, points[ tvs[ i] . C] . x, points[ tvs[ i] . C] . y,
points[ tvs[ i] . A] . x, points[ tvs[ i] . A] . y, points[ tvs[ i] . B] . x, points[ tvs[ i] . B] . y) ) {
this . add ( index, tvs[ i] . A, tvs[ i] . B) ;
}
if ( ! existsSize[ 1 ] [ i] &&
! this . cross (
points[ index] . x, points[ index] . y, points[ tvs[ i] . A] . x, points[ tvs[ i] . A] . y,
points[ tvs[ i] . B] . x, points[ tvs[ i] . B] . y, points[ tvs[ i] . C] . x, points[ tvs[ i] . C] . y) ) {
this . add ( index, tvs[ i] . B, tvs[ i] . C) ;
}
if ( ! existsSize[ 2 ] [ i] &&
! this . cross (
points[ index] . x, points[ index] . y, points[ tvs[ i] . B] . x, points[ tvs[ i] . B] . y,
points[ tvs[ i] . C] . x, points[ tvs[ i] . C] . y, points[ tvs[ i] . A] . x, points[ tvs[ i] . A] . y) ) {
this . add ( index, tvs[ i] . C, tvs[ i] . A) ;
}
}
}
public int build ( ) {
this . clear ( ) ;
if ( ! createEdge ( ) ||
! this . add ( 0 , np + 0 , np + 1 ) ||
! this . add ( 0 , np + 1 , np + 2 ) || ! this . add ( 0 , np + 0 , np + 2 ) ) {
return ( 0 ) ;
}
for ( int i = 1 ; i < np; i++ ) {
int [ ] lists = this . contains ( points[ i] ) ;
this . add ( i, lists) ;
this . remove ( lists) ;
}
deleteEdge ( ) ;
return ( nt) ;
}
public void draw ( Graphics2D g, Color c, Coordinate crd) {
Color saveColor = g. getColor ( ) ;
g. setColor ( c) ;
TriangleVertex tv;
Point p1, p2, p3 ;
int r;
for ( int i = 0 ; i < nt; i++ ) {
tv = ( TriangleVertex ) triangle. get ( i) ;
p1 = crd. getPosition ( points[ tv. A] . x, points[ tv. A] . y) ;
p2 = crd. getPosition ( points[ tv. B] . x, points[ tv. B] . y) ;
p3 = crd. getPosition ( points[ tv. C] . x, points[ tv. C] . y) ;
g. drawLine ( p1. x, p1. y, p2. x, p2. y) ;
g. drawLine ( p2. x, p2. y, p3. x, p3. y) ;
g. drawLine ( p3. x, p3. y, p1. x, p1. y) ;
}
for ( int i = 0 ; i < np; i++ ) {
p1 = crd. getPosition ( points[ i] . x, points[ i] . y) ;
g. setColor ( Color . red) ;
g. fillRect ( p1. x - 1 , p1. y - 1 , 3 , 3 ) ;
g. setColor ( Color . blue) ;
g. drawString ( String . valueOf ( i) , p1. x, p1. y) ;
}
g. setColor ( saveColor) ;
}
public static void main ( String [ ] args) {
int points = 10 ;
Point2D. Double [ ] pts = new Point2D. Double [ points] ;
for ( int i= 0 ; i< points; i++ ) {
pts[ i] = new Point2D. Double (
70.0 + 69.0 * Math . random ( ) + Math . random ( ) ,
10.0 + 49.0 * Math . random ( ) + Math . random ( ) ) ;
}
Delaunay delaunayT = new Delaunay ( pts) ;
int nTriangle = delaunayT. build ( ) ;
Vector triangle2 = delaunayT. triangle;
int width = 1600 ;
int height = 1024 ;
BufferedImage image = new BufferedImage ( width, height, BufferedImage . TYPE_3BYTE_BGR) ;
Graphics2D g = image. createGraphics ( ) ;
g. setColor ( new Color ( 192 , 240 , 255 ) ) ;
g. fillRect ( 0 , 0 , width, height) ;
Linear coordinate = new Linear ( 110.0 , 35.0 , width/ 2 , height/ 2 , 15 , 15 ) ;
coordinate. drawGridLine ( g, null , Color . green, 10 , 10 ) ;
delaunayT. draw ( g, Color . blue, coordinate) ;
File file = new File ( "D:/pic.jpg" ) ;
try {
ImageIO . write ( image, "jpg" , file) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
}