refer :

https://www.youtube.com/watch?v=R7dObDtw1aA

https://www.shuxuele.com/algebra/trig-finding-angle-right-triangle.html

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan

https://www.rapidtables.com/convert/number/how-radians-to-degrees.html

https://www.youtube.com/watch?v=ttO1TOs8048

https://www.youtube.com/watch?v=6MDNDjtWfMw

1. coordinate 和 css translate 是不同的东西

数学有 coordinate x,y ,

左上是 ( -x, +y )

右上是 ( +x, +y)

左下是 ( -x, -y)

右下是 ( +x, -y)

css translate 是说移动的方向.

+x 是往右

-x 是往左

+y 是往下

-y 是往上

注意 : coordinate y 和 translate y 是相反的.

2. 三角形和 tan sin cos

tan sin cos 在 js 里是 Math.cos, Math.sin, Math.tan

反向是 Math.acos, Math.asin, Math.atan

一般上我们 cos(degree) 使用的是 degree, 但是 js 使用的是 radian

所以要背一个转换的公式

radian = degree * Math.PI / 180;

export function degreeToRadian(degree: number): number {
return degree * Math.PI / 180;
} export function radianToDegree(radian: number): number {
return radian * 180 / Math.PI;
}

求三角形斜线的长度是

export function calcRadius(width: number, height: number): number {
return Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
}

求 x, y coordinate 当拥有 degree 和 radius (斜线的长度)

cos(deg) = x / radius

sin(deg) = y / radius

export function calcCoordinate(radius: number, degree: number): Xy {
return {
x: Math.cos(degreeToRadian(degree)) * radius,
y: Math.sin(degreeToRadian(degree)) * radius
}
}

求 degree 当有 x, y

单靠反推上面求 x,y 的公式,我们是无法获取 degree 的,因为 cos(135) === cos(225).

所以更好的做法是通过 tan

tan(d) = y / x

有一点要特别注意就是, x y 的正负值, 代表了它在不同区域. 这个是会直接影响 degree 的. 我们要特别处理.

export function calcDegree(coordinate: Xy): number {
const { x, y } = coordinate;
const result = radianToDegree(Math.atan(y / x));
if (x < 0 && y >= 0) {
return 180 - Math.abs(result); // 这里 result 是 negative
}
else if (x < 0 && y < 0) {
return 180 + result; // 这里 result 是 positive
}
else if (x >= 0 && y < 0) {
return 360 - Math.abs(result) // 这里 result 是 negative
}
else {
return result; // 这里 result 是 positive
}
}

最后是 js 的另一个函数来做到上面一样的效果. Math.atan2(y, x)

export function calcDegree(coordinate: Xy): number {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
const result = radianToDegree(Math.atan2(coordinate.y, coordinate.x));
return (result > 0) ? result : 360 - Math.abs(result);
}

css 的 rotate 和我们数学的方向也是不太一样的, 数学我们是 右边线开始,逆时针旋转 20 degree 是这样的. 上面的算法全部基于这个概念

所以如果我想说下面这个 x, y 顺势旋转 20 degree 算法应该是..

export function calcCoordinateAfterRotate(currentCoordinate: Xy, rotateDegree: number): Xy {
const radius = calcRadius(Math.abs(currentCoordinate.x), Math.abs(currentCoordinate.y));
const degree = calcDegree(currentCoordinate);
const degreeAfterRotate = degree - rotateDegree;
return calcCoordinate(radius, degreeAfterRotate);
}

换算 coordinate 去 translate x, y

export function calcTranslate(fromCoordinate: Xy, toCoordinate: Xy): Xy {
return {
x: toCoordinate.x - fromCoordinate.x,
y: fromCoordinate.y - toCoordinate.y
}
}

练习题 :

假设有 2 个点, a 和 b 连成一条斜线.

a = 1, 1

b = 11, 11

问 x = 7, y = 多少 ?

先做一个十字架基于 a 点, 然后换算 b 点 和 x 坐标

现在来求角度

10, 10 求一个角度, 上面已经有公式了, 用 atan2

calcDegree(10, 10);

角度是 45 degree

有 degree , 和 x, 我们可以算出 radius

cos(degree) = x / radius

radius = x / cos(degree)

8.482 = 6 / cos(45)

现在我们有了 三角形的底部 6 和 斜线 8.482

那我们要求高,公式可以用这个

radius = sqrt( pow2(x) + pow2(y) ) 求 y

8.482 = sqrt( pow2(6) + pow2(y) )

pow2(8.482) = pow2(6) + pow2(y)

pow2(8.482) - pow2(6) = pow2(y)

sqrt( pow2(8.482) - pow2(6) ) = y

y = 5.99... 进位就是 6 了

x = 6 , y = 6 这个是对应 a point 的,

记得一开始我们画了多一个十字架来找角度吗 ?

那现在我们得换算回去.

x = 6 + a.x, y = 6 + a.y;

所以最后是 7, 7

这个例子比较简单, 因为都是 positive 坐标, 如果是 negetive 角度可能会取代 225 degree

但我们计算三角形是不会有 225 degree 的,所以要特别处理一下. 看代码自己试试吧

export function calcHitLineCoordinateByXOrY(
startLineCoordinate: Xy,
endLineCoordinate: Xy,
by: 'x' | 'y',
xOrY: number
): number {
const min = Math.min(startLineCoordinate[by], endLineCoordinate[by]);
const max = Math.max(startLineCoordinate[by], endLineCoordinate[by]);
if (xOrY < min || xOrY > max) {
console.error(`bug ! x or y over line, this is impossible to hit line`);
throw 0;
}
// 对应 startLineCoordinate
endLineCoordinate = {
x: endLineCoordinate.x - startLineCoordinate.x,
y: endLineCoordinate.y - startLineCoordinate.y
}
xOrY = xOrY - startLineCoordinate[by];
const degree = calcDegree(endLineCoordinate);
const degreeInside90Degree = degree % 90;
const radius = calcRadiusByDegreeAndWidtOrhHeight(
degreeInside90Degree,
by === 'x' ? 'width':'height',
Math.abs(xOrY)
);
const widthOrHeight = Math.sqrt(Math.pow(radius, 2) - Math.pow(Math.abs(xOrY), 2));
let resultXOrY = widthOrHeight;
if (by === 'x' && degree > 180) {
resultXOrY *= -1;
}
else if (by === 'y' && degree > 90 && degree < 270) {
resultXOrY *= -1;
}
return resultXOrY + startLineCoordinate[by];
}

3. 直线方程式 Linear equation 和 斜率 slope

通常当我们想算出 2 条线交叉点坐标得时候就会用到下面这个公式了

代码表达

const lineA = {
start: { x: 1, y: 2 },
end: { x: 5, y: 6 }
} const lineB = {
start: { x: 2, y: 5 },
end: { x: 6, y: 1 }
}

那我们要求得是交叉也就是坐标 3, 4

这题就需要直线方程式 和斜率了

直线方程式是这样的

y - y0 = m * (x - x0);

x0, y0 是点的坐标, x 和 y 则是用来求交叉的

m 是 slope , 就是斜率.

我们如果有 2 条线的 x0 y0 和 m

然后把 2 个公式拿来解就可以算出 x 值和 y 值, x, y 就是交叉的坐标了.

那么我们看看这个 m 是这么来的。

最开始我们有 2 条线, 也就是 4 个坐标点.

m = (y1 - y0) / (x1 - x0)

这里有一个重要得点, 哪个坐标算是 0 哪个又应该是 1 呢?

线一定是左到右画的.

所以哪一个点的 x 比较小就是 start

线往上方走, m 将会是 positive

往下走是 negative

平行线则是 0

这个 positive negative 会影响算法的哦,别弄错.

有了这些概念,就容易了

先算出 2 条线分别的 m

然后放入直线公式里,然后就可以对解 2 个公式了

2 个公式就可以解除 x,y 了

下面是用 ts 的表达.

function calcIntersectionCoordinate(aLine: Line, bLine: Line): Xy {
if (aLine.start.x > aLine.end.x) {
aLine = { start: aLine.end, end: aLine.start }
}
if (bLine.start.x > bLine.end.x) {
bLine = { start: aLine.end, end: aLine.start }
}
const aLineSlope = (aLine.end.y - aLine.start.y) / (aLine.end.x - aLine.start.x);
const bLineSlope = (bLine.end.y - bLine.start.y) / (bLine.end.x - bLine.start.x); const x0 = aLine.start.x;
const y0 = aLine.start.y;
const m0 = aLineSlope;
const x1 = bLine.start.x;
const y1 = bLine.start.y;
const m1 = bLineSlope; const x = (-(m1 * x1) + y1 - y0 + (m0 * x0)) / (m0 - m1);
const y = (m0 * x) - (m0 * x0) + y0; return { x, y };
}

crop image 需要的基础知识的更多相关文章

  1. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  2. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

  3. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  4. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

  5. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  6. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  7. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  8. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

  9. [SQL] SQL 基础知识梳理(五) - 复杂查询

    SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...

随机推荐

  1. 延时程序执行Qt

    有时候为了让程序暂停一下,不让它一直跑下去,可以使它进入循环结构中! 例如: #include <QCoreApplication> #include <qdebug.h> # ...

  2. 回发或回调参数无效。在配置中使用 &lt;pages enableEventValidation=&quot;true&quot;/&gt; 或在页面中使用 &lt;%@ Page EnableEventValidation=&quot;true&quot; %&gt; 启用了事件验证。

    问题补充: “/Source”应用程序中的服务器错误. 回发或回调参数无效.在配置中使用 <pages enableEventValidation="true"/> 或 ...

  3. 3ds max不显示网格,转换为可编辑面片

    按G就消失了,快捷键 F3/F4切换线框和面片模式的显示

  4. UVa 1587 Box

    题意:给出6个矩形的长和宽,问是否能够构成一个长方体 先假设一个例子 2 3 3 4 2 3 3 4 4 2 4 2 排序后 2 3 2 3 3 4 3 4 4 2 4 2 如果要构成一个长方体的话, ...

  5. CSS块级元素、内联元素概念

    CSS文档流与块级元素(block).内联元素(inline),之前翻阅不少书籍,看过不少文章, 看到所多的是零碎的CSS布局基本知识,比较表面.看过O'Reilly的<CSS权威指南>, ...

  6. 关于Unity3D中的版本管理 .

    关于Unity3D中的版本管理 使用Unity3D也有一段时间了,由于团队一直使用SVN进行版本管理,现总结一下: (1) Unity3D的二进制资源必须加锁进行版本控制,因为它没办法merge: ( ...

  7. [原创]ssget过滤动态块的方式

    Autocad在2006增加了新的动态块功能,方便了对块的动态修改,但是修改动态块后,块名会变成一个匿名块,导致无法通过块名来快速过滤. 明经论坛上有人通过全选块后再来遍历筛选,我通过研究简化了这个问 ...

  8. java 中的重载与重写 抽象类与接口的区别

    . 重载与重写的区别: 重载(overload)               | 重写(override) 1 方法的名称相同,参数个数.类型不同 | 方法名称.参数列表.返回值类型与父类完全相同 2 ...

  9. 简化OSI七层网络协议

    OSI层 功能 TCP/IP协议 设备 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化,代码转换,数据解密 会 ...

  10. 初学Python——文件操作第二篇

    前言:为什么需要第二篇文件操作?因为第一篇的知识根本不足以支撑基本的需求.下面来一一分析. 一.Python文件操作的特点 首先来类比一下,作为高级编程语言的始祖,C语言如何对文件进行操作? 字符(串 ...