C# 4点和椭圆
我得了4分。。我可以用这个代码画一个多边形C# 4点和椭圆,c#,wpf,silverlight,silverlight-4.0,drawing,C#,Wpf,Silverlight,Silverlight 4.0,Drawing,我得了4分。。我可以用这个代码画一个多边形 var p = new Polygon(); p.Points.Add(new Point(0, 0)); p.Points.Add(new Point(70, 0)); p.Points.Add(new Point(90, 100)); p.Points.Add(new Point(0, 80)); 如何使用Silverlight绘制适合此多边形的“椭圆”? 这个问题还没有回答 根据Jeff M给出的信息,我创建了一个函数,返回多边形中的椭圆拟合
var p = new Polygon();
p.Points.Add(new Point(0, 0));
p.Points.Add(new Point(70, 0));
p.Points.Add(new Point(90, 100));
p.Points.Add(new Point(0, 80));
如何使用Silverlight绘制适合此多边形的“椭圆”?
这个问题还没有回答 根据Jeff M给出的信息,我创建了一个函数,返回多边形中的椭圆拟合:
Ellipse FitEllipse(Polygon poly)
{
double W0 = poly.Points[0].X;
double W1 = poly.Points[0].Y;
double X0 = poly.Points[1].X;
double X1 = poly.Points[1].Y;
double Y0 = poly.Points[2].X;
double Y1 = poly.Points[2].Y;
double Z0 = poly.Points[3].X;
double Z1 = poly.Points[3].Y;
double A = X0 * Y0 * Z1 - W0 * Y0 * Z1 - X0 * Y1 * Z0 + W0 * Y1 * Z0 - W0 * X1 * Z0 + W1 * X0 * Z0 + W0 * X1 * Y0 - W1 * X0 * Y0;
double B = W0 * Y0 * Z1 - W0 * X0 * Z1 - X0 * Y1 * Z0 + X1 * Y0 * Z0 - W1 * Y0 * Z0 + W1 * X0 * Z0 + W0 * X0 * Y1 - W0 * X1 * Y0;
double C = X0 * Y0 * Z1 - W0 * X0 * Z1 - W0 * Y1 * Z0 - X1 * Y0 * Z0 + W1 * Y0 * Z0 + W0 * X1 * Z0 + W0 * X0 * Y1 - W1 * X0 * Y0;
double D = X1 * Y0 * Z1 - W1 * Y0 * Z1 - W0 * X1 * Z1 + W1 * X0 * Z1 - X1 * Y1 * Z0 + W1 * Y1 * Z0 + W0 * X1 * Y1 - W1 * X0 * Y1;
double E = -X0 * Y1 * Z1 + W0 * Y1 * Z1 + X1 * Y0 * Z1 - W0 * X1 * Z1 - W1 * Y1 * Z0 + W1 * X1 * Z0 + W1 * X0 * Y1 - W1 * X1 * Y0;
double F = X0 * Y1 * Z1 - W0 * Y1 * Z1 + W1 * Y0 * Z1 - W1 * X0 * Z1 - X1 * Y1 * Z0 + W1 * X1 * Z0 + W0 * X1 * Y1 - W1 * X1 * Y0;
double G = X0 * Z1 - W0 * Z1 - X1 * Z0 + W1 * Z0 - X0 * Y1 + W0 * Y1 + X1 * Y0 - W1 * Y0;
double H = Y0 * Z1 - X0 * Z1 - Y1 * Z0 + X1 * Z0 + W0 * Y1 - W1 * Y0 - W0 * X1 + W1 * X0;
double I = Y0 * Z1 - W0 * Z1 - Y1 * Z0 + W1 * Z0 + X0 * Y1 - X1 * Y0 + W0 * X1 - W1 * X0;
double detT = A * E * I + B * F * G + C * D * H - A * F * H - B * D * I - C * E * G;
double J = (E * I - F * H) / detT;
double K = (C * H - B * I) / detT;
double L = (B * F - C * E) / detT;
double M = (F * G - D * I) / detT;
double N = (A * I - C * G) / detT;
double O = (C * D - A * F) / detT;
double P = (D * H - E * G) / detT;
double Q = (B * G - A * H) / detT;
double R = (A * E - B * D) / detT;
double a = J * J + M * M + P * P;
double b = J * K + M * N - P * Q;
double c = K * K + N * N - Q * Q;
double d = J * L + M * O - P * R;
double f = K * L + N * O - Q * R;
double g = L * L + O * O - R * R;
double Ex = (c * d - b * f) / (b * b - a * c);
double Ey = (a * f - b * d) / (b * b - a * c);
double Ea = Math.Sqrt(2.0 * (a * f * f + c * d * d + g * b * b - 2.0 * b * d * f - a * c * g) / ((b * b - a * c) * (Math.Sqrt((a - c) * (a - c) + 4.0 * b * b) - (a + c))));
double Eb = Math.Sqrt(2.0 * (a * f * f + c * d * d + g * b * b - 2.0 * b * d * f - a * c * g) / ((a * c - b * b) * (Math.Sqrt((a - c) * (a - c) + 4.0 * b * b) + (a + c))));
double phi = 0;
if (b == 0 && a < c) {
phi = 0;
} else if (b == 0 && a > c) {
phi = Math.PI / 2;
} else if (b != 0 && a < c) {
phi = (Math.PI / 2 - Math.Atan((a - c) / (2 * b))) / 2;
} else if (b != 0 && a > c) {
phi = (Math.PI / 2 - Math.Atan((a - c) / (2 * b))) / 2 + Math.PI / 2;
}
Ellipse el = new Ellipse();
el.Height = Ea * 2;
el.Width = Eb * 2;
el.RenderTransform = new RotateTransform(phi * 180 / Math.PI);
return el;
}
椭圆拟合椭圆(多边形多边形)
{
双W0=多边形点[0].X;
双W1=多边形点[0].Y;
双X0=多边形点[1].X;
双X1=多边形点[1].Y;
双Y0=多边形点[2].X;
双Y1=多边形点[2].Y;
双Z0=多边形点[3].X;
双Z1=多边形点[3].Y;
双A=X0*Y0*Z1-W0*Y0*Z1-X0*Y1*Z0+W0*Y1*Z0-W0*X1*Z0+W1*X0*Z0+W0*X1*Y0-W1*X0*Y0;
双B=W0*Y0*Z1-W0*X0*Z1-X0*Y1*Z0+X1*Y0*Z0-W1*Y0*Z0+W1*X0*Z0+W0*X0*Y1-W0*X1*Y0;
双C=X0*Y0*Z1-W0*X0*Z1-W0*Y1*Z0-X1*Y0*Z0+W1*Y0*Z0+W0*X1*Z0+W0*X0*Y1-W1*X0*Y0;
双D=X1*Y0*Z1-W1*Y0*Z1-W0*X1*Z1+W1*X0*Z1-X1*Y1*Z0+W1*Y1*Z0+W0*X1*Y1-W1*X0*Y1;
双E=-X0*Y1*Z1+W0*Y1*Z1+X1*Y0*Z1-W0*X1*Z1-W1*Y1*Z0+W1*X1*Z0+W1*X0*Y1-W1*X1*Y0;
双F=X0*Y1*Z1-W0*Y1*Z1+W1*Y0*Z1-W1*X0*Z1-X1*Y1*Z0+W1*X1*Z0+W0*X1*Y1-W1*X1*Y0;
双G=X0*Z1-W0*Z1-X1*Z0+W1*Z0-X0*Y1+W0*Y1+X1*Y0-W1*Y0;
双H=Y0*Z1-X0*Z1-Y1*Z0+X1*Z0+W0*Y1-W1*Y0-W0*X1+W1*X0;
双I=Y0*Z1-W0*Z1-Y1*Z0+W1*Z0+X0*Y1-X1*Y0+W0*X1-W1*X0;
双detT=A*E*I+B*F*G+C*D*H-A*F*H-B*D*I-C*E*G;
双J=(E*I-F*H)/detT;
双K=(C*H-B*I)/detT;
双L=(B*F-C*E)/detT;
双M=(F*G-D*I)/detT;
双N=(A*I-C*G)/detT;
双O=(C*D-A*F)/detT;
双P=(D*H-E*G)/detT;
双Q=(B*G-A*H)/detT;
双R=(A*E-B*D)/detT;
双a=J*J+M*M+P*P;
双b=J*K+M*N-P*Q;
双c=K*K+N*N-Q*Q;
双d=J*L+M*O-P*R;
双f=K*L+N*O-Q*R;
双g=L*L+O*O-R*R;
双Ex=(c*d-b*f)/(b*b-a*c);
双Ey=(a*f-b*d)/(b*b-a*c);
双Ea=数学Sqrt(2.0*(a*f*f+c*d*d+g*b*b-2.0*b*d*f-a*c*g)/((b*b-a*c)*(数学Sqrt((a-c)*(a-c)+4.0*b*b)-(a+c));
双Eb=Math.Sqrt(2.0*(a*f*f+c*d*d+g*b*b-2.0*b*d*f-a*c*g)/((a*c-b*b)*(Math.Sqrt((a-c)*(a-c)+4.0*b*b)+(a+c));
双φ=0;
如果(b==0&&ac){
φ=数学π/2;
}else如果(b!=0&&ac),则为else{
phi=(Math.PI/2-Math.Atan((a-c)/(2*b))/2+Math.PI/2;
}
椭圆el=新椭圆();
标高高度=Ea*2;
el.宽度=Eb*2;
el.RenderTransform=新的旋转变换(φ*180/数学π);
返回el;
}
一种方法是使用QuadraticBezierSegment
或BezierSegment
例如,像这样:
<Path Stroke="Red" StrokeThickness="2" >
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,40">
<PathFigure.Segments>
<PathSegmentCollection>
<BezierSegment Point1="0,93"
Point2="90,117"
Point3="80,50"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="2" >
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,40">
<PathFigure.Segments>
<PathSegmentCollection>
<BezierSegment Point1="0,-13"
Point2="70,-17"
Point3="80,50"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Polygon Points="0,0 70,0 90,100 0,80"></Polygon>
这仍然是一个实验,不是计算点,但它相当精确
Edit2:
您可以使用此图像和我的注释计算曲线点:
曲线有起点、中点和终点。在该图像中,起始点和结束点分别为L、M、N、O
;中间部分是W,X,Y,Z
例如,我们如何计算点L
:
借助于直线方程y=k*x+b,我们找到了直线方程AB,DC,AC,DB,AD。我们发现AC
和DB
的交叉程度如何R
。我们发现AB
和DC
的交叉是怎样的E
。然后我们找到了线ER
的方程,以及ER
和AD
的交叉方式,我们找到了L
我们如何计算点W
:
借助长度方程l=sqrt(sqr(x2-x1)+sqr(y2-y1))
找到AR的长度AW=AR/(4*pi)
借助于该系数,以及直线方程和长度方程,在求解平方方程后,我们发现W
我们发现的其他点也类似
该算法不仅适用于具有平行线的多边形,而且在这种情况下算法更简单。长度系数和长度系数相同
借助此算法,我找到了示例中3条曲线的点:
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,36">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="4.7,74.6"
Point2="39.9,88.9"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="39.9,88.9">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="83.43,92.7"
Point2="78.8,43.9"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,36">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="3.55,3.94"
Point2="31.8,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,36">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="4.7,74.6"
Point2="39.9,88.9"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="39.9,88.9">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="83.43,92.7"
Point2="78.8,43.9"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="0,36">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment Point1="3.55,3.94"
Point2="31.8,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="pathleftdown" StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment x:Name="bezleftdown" Point1="0,0"
Point2="0,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="pathrigthdown" StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment x:Name="bezrigthdown" Point1="0,0"
Point2="0,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="pathleftup" StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment x:Name="bezleftup" Point1="0,0"
Point2="0,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="pathrigthup" StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<QuadraticBezierSegment x:Name="bezrigthup" Point1="0,0"
Point2="0,0"
/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Polygon Name="pol" Points="0,0 250,0 251,340 0,341" Stroke="Red" StrokeThickness="1"></Polygon>
<Button Content="Generate" Width ="80" Height="30" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click"></Button>
private class pointXY
{
public double x;
public double y;
}
private class lineKB
{
public double k;
public double b;
public bool flagXconst = false;
public double xConst = 0;
}
private lineKB GetLineFromPonts(pointXY A, pointXY B)
{
lineKB line = new lineKB();
if ((B.x - A.x) != 0)
{
line.k = (B.y - A.y) / (B.x - A.x);
line.b = A.y - A.x * line.k;
}
else
{
line.xConst = A.x;
line.flagXconst = true;
}
return line;
}
private pointXY GetPointFromLines(lineKB a, lineKB b)
{
pointXY point = new pointXY();
if (a.flagXconst)
{
point.x = a.xConst;
point.y = a.xConst * b.k + b.b;
}else
if (b.flagXconst)
{
point.x = b.xConst;
point.y = b.xConst * a.k + a.b;
}
else
{
point.x = (a.b - b.b) / (b.k - a.k);
point.y = a.k * point.x + a.b;
}
return point;
}
private double LengthOfLine(pointXY A, pointXY B)
{
return Math.Sqrt((B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y));
}
private pointXY GetMidlePoint(pointXY S, double l, lineKB line, bool leftright)
{
double b = -2 * S.x - 2 * line.k * (-line.b + S.y);
double a = (1 + line.k * line.k);
double c = (S.x * S.x - l * l + (-line.b + S.y) * (-line.b + S.y));
double d = b*b - 4 * a * c;
double x1 = (-b + Math.Sqrt(d)) / (2 * a);
double x2 = (-b - Math.Sqrt(d)) / (2 * a);
pointXY ret = new pointXY();
if (leftright)
if (x1 > S.x) ret.x = x1;
else ret.x = x2;
else
if (x1 < S.x) ret.x = x1;
else ret.x = x2;
ret.y = line.k * ret.x + line.b;
return ret;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
pointXY A = new pointXY();
A.x = pol.Points[0].X;
A.y = pol.Points[0].Y;
pointXY B = new pointXY();
B.x = pol.Points[1].X;
B.y = pol.Points[1].Y;
pointXY C = new pointXY();
C.x = pol.Points[2].X;
C.y = pol.Points[2].Y;
pointXY D = new pointXY();
D.x = pol.Points[3].X;
D.y = pol.Points[3].Y;
lineKB AC = GetLineFromPonts(A, C);
lineKB BD = GetLineFromPonts(B, D);
pointXY R = GetPointFromLines(AC, BD);
lineKB AB = GetLineFromPonts(A, B);
lineKB BC = GetLineFromPonts(B, C);
lineKB CD = GetLineFromPonts(C, D);
lineKB DA = GetLineFromPonts(D, A);
pointXY E = GetPointFromLines(AB, CD);
lineKB ER = GetLineFromPonts(E, R);
pointXY L = GetPointFromLines(ER, DA);
pointXY N = GetPointFromLines(ER, BC);
pointXY F = GetPointFromLines(BC, DA);
lineKB FR = GetLineFromPonts(F, R);
pointXY M = GetPointFromLines(FR, AB);
pointXY O = GetPointFromLines(FR, CD);
pointXY W = GetMidlePoint(A, (LengthOfLine(A, R) / (4 * Math.PI)), AC, true);
pointXY X = GetMidlePoint(B, (LengthOfLine(B, R) / (4 * Math.PI)), BD, false);
pointXY Y = GetMidlePoint(C, (LengthOfLine(C, R) / (4 * Math.PI)), AC, false);
pointXY Z = GetMidlePoint(D, (LengthOfLine(D, R) / (4 * Math.PI)), BD, true);
pathleftup.StartPoint = new Point(L.x, L.y);
bezleftup.Point1 = new Point(W.x, W.y);
bezleftup.Point2 = new Point(M.x, M.y);
pathleftdown.StartPoint = new Point(L.x, L.y);
bezleftdown.Point1 = new Point(Z.x, Z.y);
bezleftdown.Point2 = new Point(O.x, O.y);
pathrigthdown.StartPoint = new Point(O.x, O.y);
bezrigthdown.Point1 = new Point(Y.x, Y.y);
bezrigthdown.Point2 = new Point(N.x, N.y);
pathrigthup.StartPoint = new Point(M.x, M.y);
bezrigthup.Point1 = new Point(X.x, X.y);
bezrigthup.Point2 = new Point(N.x, N.y);
}
} else if (b != 0 && a < c) {
phi = (Math.PI / 2 - Math.Atan((a - c) / (2 * b))) / 2;
} else if (b != 0 && a > c) {
} else if (b != 0 && a < c) {
phi = (Math.PI / 2 - Math.Atan((a - c) / (2 * b))) / 2;
} else if (b != 0 && a >= c) {
} else if (b != 0 && a <= c) {
phi = (Math.PI / 2 - Math.Atan((a - c) / (2 * b))) / 2;
} else if (b != 0 && a > c) {