【Java AWT 图形界面编程】在 Canvas 画布中绘制箭头图形 ( 数据准备 | 几个关键的计算公式 | 绘制箭头直线和尾翼 )

news/2024/11/29 22:52:14/

文章目录

  • 一、在 Canvas 画布中绘制箭头图形 - 要点分析
    • 1、数据准备
    • 2、绘制直线
    • 3、绘制箭头尾翼
  • 二、代码示例





一、在 Canvas 画布中绘制箭头图形 - 要点分析




1、数据准备


绘制箭头时 , 先设置一条直线的起始点和终止点 , 箭头绘制在该线段上 ;

    /*** 起始点 X, Y 坐标* 终止点 X, Y 坐标*/private int startX, startY, endX, endY;

为箭头指定一个长度 , 该长度的末尾是 箭头终点 , 在直线上确定箭头终点 , 该终点延伸出两个尾翼 , 尾翼也指定一个长度 ;

    /*** 箭头 左右两个尾翼 长度*/private int arrowWingLength = 20;/*** 箭头终点在直线的位置*/private float arrowEndRatio = 0.5F;/*** 箭头长度*/private int arrowLength;

2、绘制直线


先把箭头附着的直线 , 绘制出来 ;

        // 绘制直线g.drawLine(startX, startY, endX, endY);

3、绘制箭头尾翼


首先 , 确定起始点和终止点 , 在 x , y 轴上的差值 ;

        // 计算起始点和终止点在 x, y 方向的差值int deltaX = endX - startX;int deltaY = endY - startY;

然后 , 计算出起始点到终止点的角度 , deltaY / deltaX 是该角度的正切 , 已知正切值 , 计算角度 , 使用 Math.atan2 函数即可 , 最终计算的角度是 该直线 与 x 轴夹角 ;

在这里插入图片描述

        // 计算 直线的角度double angle = Math.atan2(deltaY, deltaX);

再后 , 使用勾股定理计算直线的长度 ;

        // 计算直线的长度int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

再后 , 根据比例计算出箭头的长度 , 根据该长度 , 确定箭头终点的坐标 ; 下图中蓝色的箭头 , 就是计算出的箭头尾部相对于起始点的增量 ;

在这里插入图片描述

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度arrowLength = (int) (len * arrowEndRatio);// 箭头终点坐标int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));

最后 , 绘制箭头的两个尾翼 , 箭头的位置 ; 尾翼的起始点 arrowEndX, arrowEndY , 终止点需要根据角度计算出来 ;

在这里插入图片描述

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));

完整代码示例 :

    // 绘制箭头private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {// 计算起始点和终止点在 x, y 方向的差值int deltaX = endX - startX;int deltaY = endY - startY;// 计算 直线的角度double angle = Math.atan2(deltaY, deltaX);// 计算直线的长度int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);// 设置箭头终点在直线的位置 , 根据比例计算出箭头长度arrowLength = (int) (len * arrowEndRatio);// 箭头终点坐标int arrowEndX = (int) (endX - arrowLength * Math.cos(angle));int arrowEndY = (int) (endY - arrowLength * Math.sin(angle));// 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));}




二、代码示例



代码示例 :

import java.awt.*;public class ArrowCanvas extends Canvas {/*** 起始点 X, Y 坐标* 终止点 X, Y 坐标*/private int startX, startY, endX, endY;/*** 箭头 左右两个尾翼 长度*/private int arrowWingLength = 20;/*** 箭头终点在直线的位置*/private float arrowEndRatio = 0.5F;/*** 箭头长度*/private int arrowLength;public ArrowCanvas(int startX, int startY, int endX, int endY) {this.startX = startX;this.startY = startY;this.endX = endX;this.endY = endY;// 设置画布大小setSize(400, 400);}public void paint(Graphics g) {// 绘制直线g.drawLine(startX, startY, endX, endY);// 绘制箭头drawArrow(g, startX, startY, endX, endY);}// 绘制箭头private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {// 计算起始点和终止点在 x, y 方向的差值int deltaX = endX - startX;int deltaY = endY - startY;// 计算 直线的角度// 返回的是 这条直线 与 x 轴的夹角// deltaY / deltaX  是该角度的正切// 已知正切值 , 计算角度 , 使用  Math.atan2 函数即可// 最终计算的角度是 该直线 与 x 轴夹角double angle = Math.atan2(deltaY, deltaX);// 计算直线的长度int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);// 设置箭头终点在直线的位置 , 根据比例计算出箭头长度arrowLength = (int) (len * arrowEndRatio);// 箭头终点坐标int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));// 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));}public static void main(String[] args) {// 创建窗口并添加 ArrowCanvas 组件Frame f = new Frame("ArrowCanvas Example");ArrowCanvas ac = new ArrowCanvas(50, 50, 200, 200);f.add(ac);// 设置窗口大小并可见f.setSize(400, 400);f.setVisible(true);}
}

执行结果 :

在这里插入图片描述


http://www.ppmy.cn/news/895347.html

相关文章

固定翼无人机结构分类

一、固定翼无人机常见的气动布局 常规布局 常规布局就是水平尾翼在主翼之后,有一个或者两个垂危的气动布局方式。这种布局技术最成熟,理论研究已经非常完善,生产技术也成熟而稳定,同其他气动布局相比各项性能比较均衡。只是由于…

【C++11】包装器 和 bind函数 的定义与 使用

包装器 在C11标准中,没有提供内置的包装器功能,但我们可以使用一些技术手段来实现包装器的效果。下面介绍两种常用的方法: 函数对象包装器 函数对象包装器(Function Object Wrapper): C11引入了 std::fu…

[MySql]表的增删查改

目录 前言: 1.插入数据 2.查询数据 2.1全列查询 2.2指定查询 2.3别名 2.4去重 2.5排序 2.6条件查询 2.7聚合查询 2.7.1group by语句 2.7.2havin语句 2.8联合查询 2.8.1内连接 2.8.2外连接 2.8.3自连接 2.8.4子查询 3.修改 4.删除 前言: 本次大多数使用…

ADRC控制算法在多旋翼飞行器上的应用

基础理论知识: 程序中涉及的部分知识点参考如下链接: ADRC算法以及参数整定: 关于ADRC算法以及参数整定(调参)的一些心得体会_西涯先生的博客-CSDN博客_adrc控制算法 ADRC算法的程序实现: ADRC与Matlab/S…

多旋翼飞行器设计与控制(五)—— 坐标系和姿态表示

多旋翼飞行器设计与控制(五)—— 坐标系和姿态表示 一、坐标系 一般的,对坐标轴与旋转正方向的定义采用右手定则。介绍两种坐标系:地球固联坐标系 与 机体坐标系 。 地球固联坐标系用于研究多旋翼飞行器相对于地面的运动状态&a…

多旋翼飞行器设计与控制(七)—— 传感器标定和测量模型

多旋翼飞行器设计与控制(七)—— 传感器标定和测量模型 一、三轴加速度计 三轴加速度计是一种惯性传感器,能够测量物体的比力,即去掉重力后的整体加速度或者单位质量上作用的非引力。当加速度计保持静止时,加速度计能…

四旋翼飞行器结构和原理

四旋翼飞行器结构和原理 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 前言:前年做电赛时留下的一套四旋翼飞行器如今只剩下四个旋翼和电机(不知道被谁给拆了,组装零件找不到了),趁着国庆几天假…

多旋翼飞行器设计与控制(四) —— 动力系统建模与估计

多旋翼飞行器设计与控制(四) —— 动力系统建模与估计 总体描述 动力系统建模分为四部分:螺旋桨建模、电机建模、电调建模和电池建模。 动力系统各器件参数设定 求解悬停时间的总体思路 动力系统模型 1、螺旋桨模型 拉力模型&#xff1a…