解两相互垂直的直线中的一个实际应用的计算公式
已知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);
}
//
}
}