问题描述
在平面直角坐标系里,给定任意两点A(x1,y1)、B(x2,y2),画一条带箭头的线段,箭头是个等腰三角形,由B、C、D三个点组成,CD作为箭头的底边垂直于线段AB, 现在已知箭头的底边长度的一半是w,箭头的高度是h,箭头与线段AB的两个夹角都是θ,求C和D点的坐标?
解法一
构建相似三角形求解
数学解法
画坐标轴平行线,并利用延长线构建相似三角形求解!!!
【解】
如上图所示:
1. 作图:
设点P(x,y)为AB和CD的交点,
过A点作x轴的平行线AH,
过B点作y轴的平行线BM, 交AH于M点,
过C点作y轴的平行线CE,
过F点作y轴的平行线DF,交AH于N点,
过P点作x轴的平行线EF,交直线CE于E,交直线DF于F,
由图可知: CE⊥EF, DF⊥EF,BM⊥AH,FN⊥AH
2. 由题意计算:
AM长度dx=x2-x1("dx∈R")
BM长度dy=y2-y1("dx∈R")
AB长度设为l, 则l^2=dx^2+dy^2
3. 根据相似三角的定义可得以下几组相似三角形:
△BPF~△BAM
△CEP~△DFP
△DFP~△DNH -> △DFP~△APH -> △DFP~△AMB
△CEP~△AMB
4. 由△BPF~△BAM可得:
PB/AB=BG/BM=PG/AM
即:
l/h=BG/dy=PG/dx
所以:
BG=l/h*dy
PG=l/h*dx
所以P点的坐标:
(x,y)=(x2-PG,y2-BG)=(x2-l/h*dx, y2-l/h*dy)
5. 由△DFP~△AMB可得:
DP/AB=DF/AM=PF/BM
即:
w/l=DF/dx=PF/dy
所以:
DF=w/l*dx
PF=w/l*dy
所以D点的坐标为:
(x+PF,y-DF)=(x+w/l*dy,y-w/l*dx)
6. 由△CEP~△AMB,与⑤同理:
CP/AB=CE/AM=PE/BM
即:
w/l=CE/dx=PE/dy
所以:
CE=w/l*dx
PE=w/l*dy
所以C点的坐标为:
(x-PE,y+CE)=(x-w/l*dy,y-w/l*dx)
所以三角箭头的三个坐标点为:
B(x2,y2)
C(x-w/l*dy,y-w/l*dx)=((x2-l/h*dx)-w/l*dy,(y2-l/h*dy)-w/l*dx)
D(x+w/l*dy,y-w/l*dx)=((x2-l/h*dx)+w/l*dy,(y2-l/h*dy)-w/l*dx)
代码实现
- Android中Canvas绘制代码:
/**
* 画带箭头的线段:构建相似三角形求解
* 起点和终点都可以有箭头
*/
private void drawArrowLine2(Canvas canvas, float x1, float y1, float x2, float y2) {
float h = 18 * 8; // 箭头的高度
float w = (float) (13.5 * 8); // 箭头底边的一半
//线段首位端点部分的(△x,△y)横纵坐标差
float dx = x2 - x1;
float dy = y2 - y1;
//线段的长度
float d = (float) Math.sqrt(dx * dx + dy * dy);
//(x,y)->(px,py)箭头底边和线段的交点
float px = x2 - (h / d * dx); //(px ∈ R实数)
float py = y2 - (h / d * dy); //(py ∈ R)
//为防止线段末尾比箭头突出,此处线段的末尾端点坐标重新计算,末端坐标=箭头底边到箭头的一半位置
float lineEndX = (px + x2) / 2;
float lineEndY = (py + y2) / 2;
canvas.drawLine(x1, y1, lineEndX, lineEndY,paint);
//在终点画箭头
Path path = new Path();
path.moveTo(x2, y2);
//利用相似三角形求出箭头另外两个点的坐标
path.lineTo(px + (w / d * dy), py - (w / d * dx));
path.lineTo(px - (w / d * dy), py + (w / d * dx));
path.close();
canvas.drawPath(path, arrowPaint);
//在起点画箭头
//(x,y)->(topPx,topPy)箭头底边和线段的交点
/*
float startPx = x1 + (h / d * dx);
float startPy = y1 + (h / d * dy);
float lineStartX = (startPx + x1) / 2;
float lineStartY = (startPy + y1) / 2;
canvas.drawLine(lineStartX, lineStartY, lineEndX, lineEndY,paint);
Path startPath = new Path();
startPath.moveTo(x1, y1);
startPath.lineTo(startPx + (w / d * dy), startPy - (w / d * dx));
topPath.lineTo(startPx - (w / d * dy), startPy + (w / d * dx));
startPath.close();
canvas.drawPath(startPath, arrowPaint);
*/
}