需求是根据飞机的线路情况,需要画直线,双直线,波浪线,虚线,连连接航路
其他都好说,这波浪线尤其不好画
搜了一圈,基本都是建议使用drawArc方法画圆弧拼接波浪线,但是及其麻烦,效果如下,并不理想
在群里问了下大佬的建议,改变思路
那么接下来,开始研究下怎么画
1.已知条件,是飞机的两个点
先画出直线看看
代码:
public static void main(String[] args) throws IOException {
BufferedImage res = null;
res = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = res.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setBackground(Color.black);
g.clearRect(0, 0, 500, 500);
int x1=200,y1=100;
int x2=400,y2=400;
g.drawLine(x1,y1,x2,y2);
String imageDir = "D:\\出图测试\\波浪";
ImageInfoUtil.write(res, imageDir, "test.png");
}
public static void write(BufferedImage subimage, String centerImageDir, String fileName) throws IOException {
FileOutputStream pointOut = null;
try {
File f = new File(centerImageDir);
if(!f.isDirectory()){
f.mkdirs();
}
pointOut = new FileOutputStream(centerImageDir+File.separator+fileName);//输出图片的地址
ImageIO.write(subimage, "png", pointOut);
}finally {
if(pointOut!=null){
pointOut.close();
}
}
}
效果:
2.根据直线求平行线
草稿:
代码:
public static void main(String[] args) throws IOException {
BufferedImage res = null;
res = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = res.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setBackground(Color.black);
g.clearRect(0, 0, 500, 500);
int x1=200,y1=100;
int x2=400,y2=400;
g.drawLine(x1,y1,x2,y2);
int[] ps= parallelLines(x1,y1,x2,y2,3);
g.setColor(Color.green);
g.drawLine(ps[0],ps[1],ps[2],ps[3]);
g.drawLine(ps[4],ps[5],ps[6],ps[7]);
String imageDir = "D:\\出图测试\\波浪";
ImageInfoUtil.write(res, imageDir, "test.png");
}
public static void write(BufferedImage subimage, String centerImageDir, String fileName) throws IOException {
FileOutputStream pointOut = null;
try {
File f = new File(centerImageDir);
if(!f.isDirectory()){
f.mkdirs();
}
pointOut = new FileOutputStream(centerImageDir+File.separator+fileName);//输出图片的地址
ImageIO.write(subimage, "png", pointOut);
}finally {
if(pointOut!=null){
pointOut.close();
}
}
}
/**
* 根据两点一直线和距离,算出两天平行线
* @param x1
* @param y1
* @param x2
* @param y2
* @param l
* @return
*/
public static int[] parallelLines(int x1, int y1, int x2, int y2,int l) {
int m = y2-y1;
int n = x2-x1;
double p = Math.sqrt(Math.pow(m, 2) + Math.pow(n, 2));
double t = p/n;
double s=m/p;
double c = n/p;
double ry=l*c;
double rx=l*s;
int x3 = (int) (x2-rx);
int x4=(int)(x1-rx);
int y3 = (int) (y2+ry);
int y4=(int)(y1+ry);
int x5 = (int) (x2+rx);
int x6=(int)(x1+rx);
int y5 = (int) (y2-ry);
int y6=(int)(y1-ry);
return new int[]{x3,y3,x4,y4,x5,y5,x6,y6};
}
效果
3.以已知两点为首尾,两平行线上取点,进行连接为折线(需要用到直线公式计算斜率这不贴草稿了)
代码:稍微封装了一下
public class DTest {
public static void main(String[] args) throws IOException {
BufferedImage res = null;
res = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = res.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setBackground(Color.black);
g.clearRect(0, 0, 500, 500);
int x1=200,y1=100;
int x2=400,y2=400;
g.drawLine(x1,y1,x2,y2);
int[] ps= CoordinateUtil.parallelLines(x1,y1,x2,y2,3);
g.setColor(Color.green);
g.drawLine(ps[0],ps[1],ps[2],ps[3]);
g.drawLine(ps[4],ps[5],ps[6],ps[7]);
g.setColor(Color.red);
int x3 = ps[0];
int y3 = ps[1];
int x4 = ps[2];
int y4 = ps[3];
int[] y34=null;
int[] x34=null;
int x5 = ps[4];
int y5= ps[5];
int x6 = ps[6];
int y6 = ps[7];
int[] y56=null;
int[] x56=null;
if(x1==x2){
y34 = CoordinateUtil.numbers(y3,y4);
x34 = new int[y34.length];
for (int i = 0; i < x34.length; i++) {
x34[i]=x3;
}
y56 = CoordinateUtil.numbers(y5,y6);
x56 = new int[y56.length];
for (int i = 0; i < x56.length; i++) {
x56[i]=x5;
}
}else{
x34 = CoordinateUtil.numbers(x3,x4);
double k34=CoordinateUtil.K(y3,y4,x3,x4);
double b34=CoordinateUtil.B(y3,x3,k34);
y34 = CoordinateUtil.pointY(x34,k34,b34);
x56 = CoordinateUtil.numbers(x5,x6);
double k56=CoordinateUtil.K(y5,y6,x5,x6);
double b56=CoordinateUtil.B(y5,x5,k56);
y56 = CoordinateUtil.pointY(x56,k56,b56);
}
CoordinateUtil.XY[] xy34=new CoordinateUtil.XY[y34.length];
CoordinateUtil.XY[] xy56=new CoordinateUtil.XY[y56.length];
for (int i = 0; i < y34.length; i++) {
xy34[i] = new CoordinateUtil.XY(x34[i],y34[i]);
}
for (int i = 0; i < y56.length; i++) {
xy56[i]=new CoordinateUtil.XY(x56[i],y56[i]);
}
CoordinateUtil.XY[] polys = CoordinateUtil.polyXYs(new CoordinateUtil.XY(x1,y1),new CoordinateUtil.XY(x2,y2),xy34,xy56,3);
int[] polyX = new int[polys.length];
int[] polyY = new int[polys.length];
for (int i = 0; i < polys.length; i++) {
polyX[i]=polys[i].x;
polyY[i]=polys[i].y;
}
g.drawPolyline(polyX, polyY, polyX.length);
String imageDir = "D:\\出图测试\\波浪";
ImageInfoUtil.write(res, imageDir, "test.png");
}
public static void write(BufferedImage subimage, String centerImageDir, String fileName) throws IOException {
FileOutputStream pointOut = null;
try {
File f = new File(centerImageDir);
if(!f.isDirectory()){
f.mkdirs();
}
pointOut = new FileOutputStream(centerImageDir+File.separator+fileName);//输出图片的地址
ImageIO.write(subimage, "png", pointOut);
}finally {
if(pointOut!=null){
pointOut.close();
}
}
}
}
public class CoordinateUtil {
/**
* 根据两个值,获取中间所有数
* 包含首尾
* @param x1
* @param x2
* @return
*/
public static int[] numbers(int x1, int x2) {
int max = Math.max(x1, x2);
int min = Math.min(x1, x2);
int index=0;
int [] px = new int[max-min+1];
for (int i = min; i <= max; i++) {
px[index]=i;
index++;
}
return px;
}
/**
* 求常量B
* @param y
* @param x
* @param k
* @return
*/
public static double B(int y, int x, double k) {
double b = new BigDecimal(String.valueOf(y)).subtract(new BigDecimal(new BigDecimal(String.valueOf(k)).multiply(new BigDecimal(String.valueOf(x))).doubleValue())).doubleValue();
return b;
}
/**
* 求斜率k
* @param y1
* @param y2
* @param x1
* @param x2
* @return
*/
public static double K(int y1, int y2, int x1, int x2) {
if(x2 - x1==0){
throw new RuntimeException("x2与x1相等,没有斜率");
}
double k = new BigDecimal(String.valueOf(y2 - y1)).divide(new BigDecimal(String.valueOf(x2 - x1)),5, BigDecimal.ROUND_HALF_UP).doubleValue();
return k;
}
/**
* 根据两点一直线和距离,算出两天平行线
* @param x1
* @param y1
* @param x2
* @param y2
* @param l
* @return
*/
public static int[] parallelLines(int x1, int y1, int x2, int y2,int l) {
int m = y2-y1;
int n = x2-x1;
double p = Math.sqrt(Math.pow(m, 2) + Math.pow(n, 2));
double t = p/n;
double s=m/p;
double c = n/p;
double ry=l*c;
double rx=l*s;
int x3 = (int) (x2-rx);
int x4=(int)(x1-rx);
int y3 = (int) (y2+ry);
int y4=(int)(y1+ry);
int x5 = (int) (x2+rx);
int x6=(int)(x1+rx);
int y5 = (int) (y2-ry);
int y6=(int)(y1-ry);
return new int[]{x3,y3,x4,y4,x5,y5,x6,y6};
}
/**
* 根据中间两点取首位点
* @param xy1 首
* @param xy2 尾
* @param xy34 平行线1
* @param xy56 平行线2
* @param interval 波浪间隔
* @return
*/
public static XY[] polyXYs(XY xy1, XY xy2, XY[] xy34, XY[] xy56,int interval) {
if(xy34.length!= xy56.length){
throw new RuntimeException("两条平行线长度应相同");
}
List<XY> xyList = new ArrayList<>();
xyList.add(xy1);
int lg=1;
for (int i = interval; i < xy34.length; i+=interval) {
if(i>xy34.length){
break;
}
if(lg%2==1){
xyList.add(xy34[i]);
}else{
xyList.add(xy56[i]);
}
lg++;
}
xyList.add(xy2);
return xyList.toArray(new XY[xyList.size()]);
}
public static class XY{
public int x;
public int y;
public XY(int x, int y) {
this.x = x;
this.y = y;
}
}
/**
* y=kx+b
* @param px
* @param k
* @param b
* @return
*/
public static int[] pointY(int[] px, double k, double b) {
int[] py = new int[px.length];
for (int i = 0; i < px.length; i++) {
py[i]=new BigDecimal(k).multiply(new BigDecimal(px[i])).add(new BigDecimal(b)).intValue();
}
return py;
}
}
效果:
去掉辅助的平行线和直线看看,对比一下效果还不错
代码未整理封装,有空再说