• 矩阵、分数、点、线类


    Matrix,Fraction,Point,Line

    //计算几何误差修正
    Math.EPS=0.00000001;
    //判断x的符号
    Math.cmp=function(x) {
    if(Math.abs(x)<Math.EPS)return 0;
    if(x>0){
    return 1;
    }else{
    return -1;
    }
    }
    //矩阵类
    class Matrix {
    //将一个数组构建成一个矩阵,行Row、列Column
    constructor(data,Row,Column){
    this.data=data||[];
    this.Row=Row;//行
    this.Column=Column;//竖
    }
    //根据行、列返回矩阵元素
    getItem(r,c){
    return this.data[r*this.Column+c]||0;
    }
    //根据行、列设置矩阵元素
    setItem(r,c,item){
    this.data[r*this.Column+c]=item;
    }
    //换行
    swapRow(r1,r2){
    for(let c=0;c<this.Column;c++){
    const cache=this.getItem(r1,c)
    this.setItem(r1,c,this.getItem(r2,c))
    this.setItem(r2,c,cache);
    }
    }
    oneRowEach(r,callback){
    for(let c=0;c<this.Column;c++){
    callback(this.getItem(r,c),r,c)
    }
    }
    //按行遍历矩阵元素,返回元素item,行r,列c
    rowEach(callback){
    for(let r=0;r<this.Row;r++){
    for(let c=0;c<this.Column;c++){
    callback(this.getItem(r,c),r,c)
    }
    }
    }
    //按竖遍历矩阵元素,返回元素item,行r,列c
    columnEach(callback){
    for(let c=0;c<this.Column;c++){
    for(let r=0;r<this.Row;r++){
    callback(this.getItem(r,c),r,c)
    }
    }
    }
    //行循环
    oneRowMap(r,callback){
    this.oneRowEach(r,(item,r,c)=> {
    this.setItem(r,c,callback(item,r,c));
    })
    }
    //按行map矩阵元素
    rowMap(callback){
    this.rowEach((item,r,c)=> {
    this.setItem(r,c,callback(item,r,c));
    })
    }
    //相加
    add(matrix){
    if(matrix instanceof Matrix&& this.Row === matrix.Row && this.Column === matrix.Column){
    const nMatrix=new Matrix([],this.Row,this.Column)
    this.rowEach(function (item,r,c) {
    nMatrix.setItem(r,c,item+matrix.getItem(r,c))
    })
    return nMatrix;
    }else{
    throw '方法plus 参数错误';
    }
    }
    //相减
    sub(matrix){
    if(matrix instanceof Matrix&& this.Row === matrix.Row && this.Column === matrix.Column){
    const nMatrix=new Matrix([],this.Row,this.Column)
    this.rowEach(function (item,r,c) {
    nMatrix.setItem(r,c,item-matrix.getItem(r,c))
    })
    return nMatrix;
    }else{
    throw '方法minus 参数错误';
    }
    }
    //相乘
    multiply(obj){
    if(obj instanceof Matrix){
    return this.multiplyMatrix(obj)
    }else if(typeof obj=='number'){
    return this.multiplyNumber(obj)
    }else{
    throw 'multiply 输入的参数类型错误';
    }
    }
    //矩阵与数相乘,返回一个新的矩阵
    multiplyNumber(number){
    const nMatrix=new Matrix([],this.Row,this.Column)
    this.rowEach((item,r,c)=> {
    nMatrix.setItem(r,c,item*number)
    })
    return nMatrix;
    }
    //矩阵与矩阵相乘 矩阵A的行必须与矩阵B的列数相等
    multiplyMatrix(matrix){
    if(this.Row!==matrix.Column){
    throw '矩阵A的行必须与矩阵B的列数相等';
    }
    const nMatrix=new Matrix([],this.Row,matrix.Column)
    for(let r=0;r<this.Row;r++){
    for(let mc=0;mc<matrix.Column;mc++){
    let num=0;
    for(let c=0;c<this.Column;c++){
    num=num+this.getItem(r,c)*matrix.getItem(c,mc)
    }
    nMatrix.setItem(r,mc,num)
    }
    }
    return nMatrix;

    }
    //切割
    cut({r,c,w,h}){
    const mt=this;
    const nMt=new Matrix([],h,w);
    nMt.rowMap(function (item,r1,c1) {
    return mt.getItem(r+r1,c+c1)
    })
    return nMt;
    }
    //复制生成一个新的矩阵
    clone(){
    return new Matrix([].concat(this.data),this.Row,this.Column)
    }
    //转换成字符图形
    toString(){
    let str='[';
    for(let r=0;r<this.Row;r++){
    str=str+' '
    for(let c=0;c<this.Column;c++){
    if(r==this.Row-1&&c==this.Column-1){
    str=str+this.getItem(r,c);
    }else{
    str=str+this.getItem(r,c)+',';
    }
    }
    }
    str=str+' ]'
    return str;
    }
    }

    /*Gauss 消元
    传入一个矩阵,传出结果
    */
    function Gauss(matrix){
    let l=[];//是否为自由元
    let ans=[];//存储解
    const n=matrix.Column-1;//解的个数
    let res=0,r=0;
    for(let i=0;i<matrix.Column;i++){
    for(let j=r;j<matrix.Row;j++){
    if(Math.abs(matrix.getItem(j,i))>Math.EPS){
    if(j!==r){
    //行交换位置
    for(let k=i;k<=n;k++){
    const temp1=matrix.getItem(j,k)
    const temp2=matrix.getItem(r,k)
    matrix.setItem(j,k,temp2)
    matrix.setItem(r,k,temp1)
    }
    }
    break;
    }
    }
    // console.log(matrix.toString(),r,i)
    if(Math.abs(matrix.getItem(r,i)<Math.EPS)){
    ++res;
    console.log('continue')
    continue;
    }
    //方程相减,消除元
    for(let j=0;j<matrix.Row;j++){
    if(j!==r&&Math.abs(matrix.getItem(j,i))>Math.EPS){
    let tmp=matrix.getItem(j,i)/matrix.getItem(r,i);
    for(let k=i;k<=n;k++){
    const item=matrix.getItem(j,k)-tmp*matrix.getItem(r,k)
    matrix.setItem(j,k,item)
    }

    }
    }
    l[i]=true;
    r++;
    }
    //输出答案
    for(let i=0;i<n;i++){
    if(l[i]){
    for(let j=0;j<n;j++){
    if(Math.abs(matrix.getItem(j,i))>0){
    ans[i]=matrix.getItem(j,n)/a.getItem(j,i)
    }
    }
    }
    }
    return ans;
    }
    //将一个矩阵转换成上三角矩阵
    function upperMatrix(oriMatrix) {
    const matrix=oriMatrix.clone();
    let r=0;

    //生成上三角矩阵
    for(let i=0;i<matrix.Row;i++){
    //循环行
    for(let j=r;j<matrix.Row;j++){
    if(Math.abs(matrix.getItem(j,i))>Math.EPS){
    if(j!==r){
    //行交换位置
    matrix.swapRow(j,r)
    }

    break;
    }
    }
    if(Math.abs(matrix.getItem(r,i)<Math.EPS)){
    continue;
    }
    //方程相减,消除元
    for(let j=0;j<matrix.Row;j++){
    if(j!==r&&Math.abs(matrix.getItem(j,i))>Math.EPS){
    let tmp=matrix.getItem(j,i)/matrix.getItem(r,i);
    for(let k=i;k<matrix.Column;k++){
    const item=matrix.getItem(j,k)-tmp*matrix.getItem(r,k)
    matrix.setItem(j,k,item)
    }
    }
    }
    r++;
    }

    return matrix
    }

    //求矩阵的逆
    function Inverse(matrix){
    if(matrix.Row!==matrix.Column){
    throw '矩阵的行与列需要相等';
    }
    const N=matrix.Row;
    //方程矩阵A
    const A = new Matrix([],N,2*N);
    for(let r=0;r<N;r++){
    for(let c=0;c<N;c++){
    A.setItem(r,c,matrix.getItem(r,c))
    }
    }
    for(let r=0;r<N;r++){
    for(let c=N;c<N*2;c++){
    if(r===c-N){
    A.setItem(r,c,1)
    }else{
    A.setItem(r,c,0)
    }
    }
    }
    //换成上三角矩阵
    const B=upperMatrix(A)

    //左边转成单位矩阵
    for(let i=0;i<N;i++){
    if(Math.abs(B.getItem(i,i))!==1){
    for(let k=N;k<2*N;k++){
    B.setItem(i,k,B.getItem(i,k)/B.getItem(i,i))
    }
    B.setItem(i,i,1)
    }
    }
    //输出结果
    const C = new Matrix([],N,N);
    C.rowMap(function (item,r,c) {
    return B.getItem(r,c+N);
    })
    return C;
    }
    //欧几里得算法 求两个数a、b的最大公约数
    function gcd(a,b){
    return b===0?a:gcd(b,a%b)
    }
    //分数类 分子,分母
    class Fraction{
    constructor(num=0,den=1){
    if(den<0){
    num=-num;
    den=-den;
    }
    if(den===0){
    throw '分母不能为0'
    }
    let g=gcd(Math.abs(num),den)
    this.num=num/g;
    this.den=den/g;
    }
    //加
    add(o){
    return new Fraction(this.num*o.den+this.den*o.num,this.den*o.den)
    }
    //减
    sub(o){
    return new Fraction(this.num*o.den-this.den*o.num,this.den*o.den)
    }
    //乘
    multiply(o){
    return new Fraction(this.num*o.num,this.den*o.den);
    }
    //除
    divide(o){
    return new Fraction(this.num*o.den,this.den*o.num);
    }
    //小于
    lessThan(o){
    return this.num*o.den<this.den*o.num;
    }
    //等于
    equal(o){
    return this.num*o.den===this.den*o.num;
    }
    }

    //点类
    function Point(x,y) {
    if(this instanceof Point){
    if(Math.cmp(x.toFixed(2)-x)==0){
    x=Number(x.toFixed(2));
    }
    if(Math.cmp(y.toFixed(2)-y)==0){
    y=Number(y.toFixed(2));
    }
    this.x=x;
    this.y=y;
    }else{

    return new Point(x,y)
    }
    }
    //向量的模长
    Point.prototype.norm=function(){
    return Math.sqrt(this.x*this.x+this.y*this.y);
    }
    // 加
    Point.add=function(a,b){
    return new Point(a.x+b.x,a.y+b.y)
    }
    // 减
    Point.sub=function(a,b){
    return new Point(a.x-b.x,a.y-b.y);
    }
    // 等于
    Point.equals=function(a,b){
    return Math.cmp(a.x-b.x)===0&&Math.cmp(a.y-b.y)===0;
    }
    //乘 向量与数字
    Point.multiply=function(a,b){
    if(a instanceof Point&&typeof b=='number'){
    return Point(a.x*b,a.y*b)
    }
    if(b instanceof Point&&typeof a=='number'){
    return Point(a*b.x,a*b.y)
    }
    }
    //除 向量与数字
    Point.divide=function(a,b){
    return Point(a.x/b,a.y/b)
    }
    //向量的叉积
    Point.det=function (a,b) {
    return a.x*b.y-a.y*b.x;
    }
    //向量的点积
    Point.dot=function (a,b) {
    return a.x*b.x+a.y*b.y;
    }
    //两个点的距离
    Point.dist=function (a,b) {
    return Point.sub(a,b).norm()
    }
    //逆时针旋转,a为弧度
    Point.rotate=function (p,A) {
    if(A===0){return p;}
    const tx=p.x;
    const ty=p.y;
    return Point(tx*Math.cos(A)-ty*Math.sin(A),tx*Math.sin(A)+ty*Math.cos(A))
    }

    //计算几何线段类
    function Line(a,b) {
    if(this instanceof Line){
    this.a=a;
    this.b=b;
    }else{
    if(a instanceof Point&&b instanceof Point){
    return new Line(a,b)
    }else{
    throw 'Line 参数错误'
    }
    }
    }
    //点p到线段s、t的距离
    Line.dis_point_segment=function(p,s,t){
    if(Math.cmp(Point.dot(Point.sub(p,s),Point.sub(t,s)))<0){
    return Point.sub(p,s).norm()
    }
    if(Math.cmp(Point.dot(Point.sub(p,t),Point.sub(s,t)))<0){
    return Point.sub(p,t).norm()
    }
    return Math.abs(Point.det(Point.sub(s,p),Point.sub(t,p))/Point.dist(s,t))
    }
    //点到线段的垂足
    Line.pointProjLine=function(p,s,t){
    const r=Point.dot(Point.sub(t,s),Point.sub(p,s))/Point.dot(Point.sub(t,s),Point.sub(t,s))
    return Point.add(s,Point.multiply(r,Point.sub(t,s)))
    }
    //点是否在线段上
    Line.pointOnSegment=function(p,s,t){
    return Math.cmp(Point.det(Point.sub(p,s),Point.sub(t,s)))===0&&Math.cmp(Point.det(Point.sub(p,s),Point.sub(p,t)))<=0
    }
    //判断线段a、b是否平行,a、b 为line
    Line.parallel=function (a,b) {
    return !Math.cmp(Point.det(Point.sub(a.a,a.b),Point.sub(b.a,b.b)))
    }
    //判断线段a、b是否相交,返回交点
    Line.lineMakePoint=function (a,b) {
    if(Line.parallel(a,b)){
    return false;
    }
    const s1=Point.det(Point.sub(a.a,b.a),Point.sub(b.b,b.a));
    const s2=Point.det(Point.sub(a.b,b.a),Point.sub(b.b,b.a));
    return Point.divide(Point.sub(Point.multiply(s1,a.b),Point.multiply(s2,a.a)),s1-s2);
    }
    // 将直线a沿法向量方向平移距离len得到的直线
    Line.moveD=function (a,len) {
    let d=Point.sub(a.b,a.a)
    d=Point.divide(d,d.norm());
    d=Point.rotate(d,Math.PI/2);
    return Line(Point.add(a.a,Point.multiply(d,len)),Point.add(a.b,Point.multiply(d,len)))
    }
    module.exports={
    Matrix,
    Fraction,
    Point,
    Line
    }
  • 相关阅读:
    vagrant 修改配置生效
    Linux下如何获取CPU内存等硬件信息
    linux命令系列 sudo apt-get update和upgrade的区别
    docker-compose up 启动容器服务超时错误:ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug information
    ERROR: manifest for hyperledger/fabric-orderer:latest not found
    fabric2.0开发 部署fabric环境和fabric-samples的启动(2)
    开源架构Fabric、FISCO BCOS(以下简称“BCOS”)、CITA 技术对比
    Centos 7 安装配置 Mariadb 数据库
    liblzma.so.5: version `XZ_5.1.2alpha' not found (required by /lib64/librpmio.so.3)
    ImportError: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
  • 原文地址:https://www.cnblogs.com/caoke/p/11096669.html
Copyright © 2020-2023  润新知