原文链接
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();
}
}
}