解两相互垂直的直线中的一个实际应用的计算公式

博客围绕两相互垂直直线的实际应用,已知过两点的直线方程及其中间点坐标,求解过中间点且垂直于该直线、与中间点距离为d的坐标对(x0,y0)的计算公式,还给出Mathematica 9的下载地址、安装方法及用法,最后展示了C#实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解两相互垂直的直线中的一个实际应用的计算公式

已知L(Ax+By+C=0)的过p1(x1,y1),p2(x2,y2)两点的直线方程
且p3(x3,y3)是p1到p2两点间的中间点坐标
求过p3且垂直于L的直线中的两个点到p3的距离为d的坐标对(x0,y0)的计算公式?
在这里插入图片描述
k=(y2-y1)/(x2-x1)
A=k
B=-1
C=y1-k*x1

联合解方程组
d^2 == (x3 - x0)^2 + (y3 - y0)^2
(y0 - y3)== -1/k(x0 -x3)

Solve[{d^2 == (x3 - x0)^2 + (y3 - y0)^2, (y0 - y3)*k == -(x0 - x3)}, {x0, y0}]

结果为
x0=-dk/(1+k2)(1/2)+x3+ky3-ky3/(1+k2)-k3y3/(1+k^2)
y0=(d*(1+k2)(1/2)+y3+k2*y3)/(1+k2)

x0=dk/(1+k2)(1/2)+x3+ky3-ky3/(1+k2)-k3y3/(1+k^2)
y0=(-d*(1+k2)(1/2)+y3+k2*y3)/(1+k2)

求解需要的点(x0,y0)的计算公式为:

在这里插入图片描述
Mathematica 9
附下载地址:链接:https://pan.baidu.com/s/1pL7HIAJ 密码:vylx

附安装方法:
https://jingyan.baidu.com/article/1876c852b44b8a890b1376ef.html
附用法:

简单例子
//---------------------------------------------------------------------------------------
In[6]:= Solve[{x^2+y^2==1,x+y==1},{x,y}]

Out[6]= {{x -> 0, y -> 1}, {x -> 1, y -> 0}}

简单例子
//---------------------------------------------------------------------------------------
Solve[{a+b==5,a*b==6},{a,b}]

结果为Out[3]= {{a -> 2, b -> 3}, {a -> 3, b -> 2}}
//---------------------------------------------------------------------------------------

线顺时针方向走向时在线外边标注
在这里插入图片描述
在这里插入图片描述

线反时针方向走向时在线外边标注
在这里插入图片描述

C#实现代码如下所示:

private double getLineLength(IPoint p1,IPoint p2)
        {
            ILine L = new LineClass();
            L.FromPoint = p1;
            L.ToPoint = p2;
            return L.Length;
        }
        //获取线段的方向角
        public double getAngleOfLine(IPoint pt1, IPoint pt2)
        {
            double a = 0;
            ILine l = new LineClass();
            l.FromPoint = pt1;
            l.ToPoint = pt2;
            a = l.Angle;  //返回值[-180,0,+180]
            a = a * 180 / Math.PI;
            if (a < 0)
            {
                a = 360 + a; //return [0,360]
            }
            l = null;
            return a;
        }
        //private double getAngleOfLine(IPoint p1,IPoint p2)
        //{
        //    return Math.Atan2((p2.Y - p1.Y), (p2.X - p1.X)) * 180 / Math.PI;
        //}   返回值[-180,0,+180]
        private IPoint getCenterPoint(IPoint p1,IPoint p2)
        {
            LineClass L = new LineClass();
            L.FromPoint = p1;
            L.ToPoint = p2;
            IPoint pi = new PointClass();
            L.ICurve_QueryPoint(esriSegmentExtension.esriNoExtension, L.Length/2.0, false, pi);
            //IPoint p = new PointClass();
            //p.X = (p1.X + p2.X) / 2.0;
            //p.Y= (p1.Y + p2.Y) / 2.0;
            return pi;
        }
        //点到直线的垂足点
        public static IPoint getFootPoint(IPoint point, IPoint pnt1, IPoint pnt2)
        {
            double A = pnt2.Y - pnt1.Y;     //y2-y1
            double B = pnt1.X - pnt2.X;     //x1-x2;
            double C = pnt2.X * pnt1.Y - pnt1.X * pnt2.Y;     //x2*y1-x1*y2
            if (A * A + B * B < 1e-13)
            {
                return pnt1;   //pnt1与pnt2重叠
            }
            else if (Math.Abs(A * point.X + B * point.Y + C) < 1e-13)
            {
                return point;   //point在直线上(pnt1_pnt2)
            }
            else
            {
                double x = (B * B * point.X - A * B * point.Y - A * C) / (A * A + B * B);
                double y = (-A * B * point.X + A * A * point.Y - B * C) / (A * A + B * B);
                IPoint fpoint = new PointClass();
                fpoint.X = x;
                fpoint.Y = y;
                return fpoint;
            }
        }
        //过直线段的中心点垂直距离为d的两个点坐标
        public static IPoint getPointLine90(IPoint p3, double d,IPoint pnt1,IPoint pnt2)
        {
            double A = pnt2.Y - pnt1.Y;     //y2-y1
            double B = pnt1.X - pnt2.X;     //x1-x2;
            double C = pnt2.X * pnt1.Y - pnt1.X * pnt2.Y;     //x2*y1-x1*y2
            if(B< 1e-13)
            {    //与Y轴重叠
                IPoint pp = new PointClass();
                pp.X = p3.X + d;
                pp.Y = p3.Y;
                return pp;
            }
            double K = -1 * A / B;
            double KK = K * K;
            double KKK = KK * K;
            double KK_1 = 1 + KK;
            double sqrt_1_kk = Math.Sqrt(1 + KK);
            //point在直线上(pnt1_pnt2)
            double x = 1 * d * K / sqrt_1_kk + p3.X + K * p3.Y - (K * p3.Y) / KK_1 - (KKK * p3.Y) / KK_1;
            double y = (-1*d * sqrt_1_kk + p3.Y + KK * p3.Y) / KK_1;
            //
            IPoint p = new PointClass();
            p.X = x;
            p.Y = y;
            return p;
            //            
        }
        public static IPoint getPointLine90_1(IPoint p3, double d, IPoint pnt1, IPoint pnt2)
        {
            double A = pnt2.Y - pnt1.Y;     //y2-y1
            double B = pnt1.X - pnt2.X;     //x1-x2;
            double C = pnt2.X * pnt1.Y - pnt1.X * pnt2.Y;     //x2*y1-x1*y2
            if (B < 1e-13)
            {    //与Y轴重叠
                IPoint pp = new PointClass();
                pp.X = p3.X - d;
                pp.Y = p3.Y;
                return pp;
            }
            double K = -1 * A / B;
            double KK = K * K;
            double KKK = KK * K;
            double KK_1 = 1 + KK;
            double sqrt_1_kk = Math.Sqrt(1 + KK);
            //point在直线上(pnt1_pnt2)
            double x = -1 * d * K / sqrt_1_kk + p3.X + K * p3.Y - (K * p3.Y) / KK_1 - (KKK * p3.Y) / KK_1;
            double y = (d * sqrt_1_kk + p3.Y + KK * p3.Y) / KK_1;
            //
            IPoint p = new PointClass();
            p.X = x;
            p.Y = y;
            return p;
            //            
        }
        private double newAngleZJ(double AofLine)
        {            
            if (AofLine >= 270.0)
            {
            }
            else if (AofLine >= 180.0)
            {
                AofLine = AofLine - 180.0;
            }                
            else if (AofLine >= 90.0)
            {
                AofLine = AofLine + 180.0;
            }           
            return AofLine;
        }
        //创建房屋界线长度注记
        private void createZJ_lineLength(ZHFeaturePolyLine from_zhFeat, IFeatureClass toFc)
        {
            string FontName = "宋体";
            double FontSize = 4;
            double FontAngle = 0;
            IColor pColor = this.ConvertColorToIColor(255, 0, 0);   //rgb
            //
            double x = 0;
            double y = 0;
            IGeometry geo = from_zhFeat.pFeature.ShapeCopy;
            if (geo != null && geo is IPolyline)
            {
                IPoint[] pointArray = this.getPoints(geo as IPolyline).ToArray();
                if (pointArray != null && pointArray.Length <=2)
                {   //跳过 不能构面的线
                    return;
                }
                //开始点
                //writeZJPoint(pointArray[0],"开始点",0, from_zhFeat, toFc);                

                //长度注记
                for (int i=0;i<pointArray.Length;i++)
                {                    
                    //
                    int lastIndex = i + 1;
                    if(lastIndex>=pointArray.Length)
                    {
                        break;
                    }
                    double L = getLineLength(pointArray[i], pointArray[i + 1]);
                    L = Math.Round(L, 2);
                    IPoint cPoint = getCenterPoint(pointArray[i], pointArray[i + 1]);
                    //
                    IPoint zjPoint = cPoint;// getPointLine90(cPoint, 1, pointArray[i], pointArray[i + 1]);
                    //
                    double AofLine = this.getAngleOfLine(pointArray[i], pointArray[i + 1]);
                    //修正角
                    double newAngleZJ = this.newAngleZJ(AofLine);
                    //
                    System.Console.WriteLine(AofLine);
                    double oldAngle = AofLine;                    
                    zjPoint = getPointLine90_1(cPoint, 1, pointArray[i], pointArray[i + 1]);
                    double A_c_p = this.getAngleOfLine(cPoint, zjPoint);                    
                    double add90 = oldAngle + 90;
                    if (add90 > 360)
                    {
                        add90 = add90 - 360;                        
                    }
                    // A_c_p - oldAngle;
                    if (Math.Abs(add90 - A_c_p) < 0.0001)
                    {                                                
                    }
                    else
                    { 
                        zjPoint = getPointLine90(cPoint, 1, pointArray[i], pointArray[i + 1]);
                    }
                    if (Math.Abs(oldAngle - newAngleZJ) < 0.0001)
                    {
                        zjPoint = cPoint;
                    }
                    //
                    this.writeZJPoint(zjPoint, L.ToString(), newAngleZJ, from_zhFeat, toFc);
                    writeZJPoint(zjPoint, ".", 0, from_zhFeat, toFc);
                    writeZJPoint(cPoint, ".", 0, from_zhFeat, toFc);
                }
                //
                
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值