- function Intersect3D_2Planes( Pn1, Pn2 : TPlane; var L : TLine ):Byte;
- var u,A : TAffineFltVector;
- temp1,temp2,v,temp3:THomogeneousFltVector;
- maxc : integer; // abs max coordinate
- iP : TAffineFltVector; // intersect point
- d1, d2 : single; // the constants in the 2 plane equations
- begin
- u := VectorCrossProduct(Pn1.PlaneNormal,Pn2.PlaneNormal);
- A := u;
- //AbsVector(A);
- A[0] := abs(A[0]);
- A[1] := abs(A[1]);
- A[2] := abs(A[2]);
- // test if the two planes are parallel
- if ((a[0]+a[1]+a[2]) < geometry.EPSILON) then
- begin // Pn1 and Pn2 are near parallel
- // test if disjoint or coincide
- // v = Pn2.PointOnPlane - Pn1.PointOnPlane;
- // v := VectorSubtract(Pn2.PointOnPlane,Pn1.PointOnPlane);
- v[0] := Pn2.PointOnPlane[0] - Pn1.PointOnPlane[0];
- v[1] := Pn2.PointOnPlane[1] - Pn1.PointOnPlane[1];
- v[2] := Pn2.PointOnPlane[2] - Pn1.PointOnPlane[2];
- // if (VectorDotProduct(Pn2.PointOnPlane, v) = 0) then // Pn2.PointOnPlane lies in Pn1
- if ((Pn2.PointOnPlane[0]*v[0]+Pn2.PointOnPlane[1]*v[1]+Pn2.PointOnPlane[2]*v[2]) = 0) then
- Result := 1 // Pn1 and Pn2 coincide
- else
- Result := 0; // Pn1 and Pn2 are disjoint
- Exit;
- end;
- // Pn1 and Pn2 intersect in a line
- // first determine max abs coordinate of cross product
- if (a[0] > a[1]) then
- begin
- if (a[0] > a[2]) then
- maxc := 1
- else
- maxc := 3;
- end
- else if (a[1] > a[2]) then
- maxc := 2
- else
- maxc := 3;
- // next, to get a point on the intersect line
- // zero the max coord, and solve for the other two
- // d1 := - VectorDotProduct(Pn1.PlaneNormal, Pn1.PointOnPlane);
- d1 := -(Pn1.PlaneNormal[0]*Pn1.PointOnPlane[0]+Pn1.PlaneNormal[1]*Pn1.PointOnPlane[1]+Pn1.PlaneNormal[2]*Pn1.PointOnPlane[2]);
- // d2 := - VectorDotProduct(Pn2.PlaneNormal, Pn2.PointOnPlane);
- d2 := -(Pn2.PlaneNormal[0]*Pn2.PointOnPlane[0]+Pn2.PlaneNormal[1]*Pn2.PointOnPlane[1]+Pn2.PlaneNormal[2]*Pn2.PointOnPlane[2]);
- case (maxc) of // select max coordinate
- 1: begin // intersect with x=0
- iP[0] := 0;
- iP[1] := (d2 * Pn1.PlaneNormal[2] - d1 * Pn2.PlaneNormal[2]) / u[0];
- iP[2] := (d1 * Pn2.PlaneNormal[1] - d2 * Pn1.PlaneNormal[1]) / u[0];
- end;
- 2: begin // intersect with y=0
- iP[0] := (d1 * Pn2.PlaneNormal[2] - d2 * Pn1.PlaneNormal[2]) / u[1];
- iP[1] := 0;
- iP[2] := (d2 * Pn1.PlaneNormal[0] - d1 * Pn2.PlaneNormal[0]) / u[1];
- end;
- 3: begin // intersect with z=0
- iP[0] := (d2 * Pn1.PlaneNormal[1] - d1 * Pn2.PlaneNormal[1]) / u[2];
- iP[1] := (d1 * Pn2.PlaneNormal[0] - d2 * Pn1.PlaneNormal[0]) / u[2];
- iP[2] := 0;
- end;
- end;
- L.PointOnLine1 := iP;
- L.PointOnLine2[0] := iP[0]+u[0];
- L.PointOnLine2[1] := iP[1]+u[1];
- L.PointOnLine2[2] := iP[2]+u[2];
- // L->P0 = iP;
- // L->P1 = iP + u;
- Result := 2;
- end;
- procedure Intersect2D_2Lines( L1,L2:TLine2D; var P:TVector2D );
- var m1,m2,
- x1,x2,
- y1,y2:single;
- begin
- m1 := (L1.PointOnLine2.y-L1.PointOnLine1.y)/(L1.PointOnLine2.x-L1.PointOnLine1.x);
- m2 := (L2.PointOnLine2.y-L2.PointOnLine1.y)/(L2.PointOnLine2.x-L2.PointOnLine1.x);
- x1 := L1.PointOnLine1.x;
- x2 := L2.PointOnLine1.x;
- y1 := L1.PointOnLine1.y;
- y2 := L2.PointOnLine1.y;
- P.x := (y2-y1+m1*x2-m2*x2)/(m1-m2);
- P.y := y1+m1*(P.x-x1);
- end;
- procedure TMap.Draw;
- //...
- procedure MakeEbene(i:integer);
- begin
- ebene.PlaneNormal[0] := Frustum.Frustum[i][0];
- ebene.PlaneNormal[1] := Frustum.Frustum[i][1];
- ebene.PlaneNormal[2] := Frustum.Frustum[i][2];
- ebene.PointOnPlane[0] := Frustum.Frustum[i][0]*Frustum.Frustum[i][3];
- ebene.PointOnPlane[1] := Frustum.Frustum[i][1]*Frustum.Frustum[i][3];
- ebene.PointOnPlane[2] := Frustum.Frustum[i][2]*Frustum.Frustum[i][3];
- end;
- procedure Swap(var a,b:single);
- var c:single;
- begin
- c := a;
- a := b;
- b := c;
- end;
- function SmallestValue(v1,v2,v3,v4:single):single;
- begin
- if v1 > v2 then
- Swap(v1,v2);
- if v1 > v3 then
- Swap(v1,v3);
- if v1 > v4 then
- Swap(v1,v4);
- result := v1;
- end;
- function GreatestValue(v1,v2,v3,v4:single):single;
- begin
- if v1 < v2 then
- Swap(v1,v2);
- if v1 < v3 then
- Swap(v1,v3);
- if v1 < v4 then
- Swap(v1,v4);
- result := v1;
- end;
- begin
- //...
- Frustum.Calculate; //TFrustum Klasse von delphigl.de
- nullebene.PointOnPlane[0] := 0;
- nullebene.PointOnPlane[1] := 0;
- nullebene.PointOnPlane[2] := 0;
- nullebene.PlaneNormal[0] := 0;
- nullebene.PlaneNormal[1] := 1;
- nullebene.PlaneNormal[2] := 0;
- //Links
- MakeEbene(Left);
- Intersect3D_2Planes(ebene,nullebene,lineTemp);
- lineLeft.PointOnLine1.x := lineTemp.PointOnLine1[0];
- lineLeft.PointOnLine1.y := lineTemp.PointOnLine1[2];
- lineLeft.PointOnLine2.x := lineTemp.PointOnLine2[0];
- lineLeft.PointOnLine2.y := lineTemp.PointOnLine2[2];
- //Rechts
- MakeEbene(Right);
- Intersect3D_2Planes(ebene,nullebene,lineTemp);
- lineRight.PointOnLine1.x := lineTemp.PointOnLine1[0];
- lineRight.PointOnLine1.y := lineTemp.PointOnLine1[2];
- lineRight.PointOnLine2.x := lineTemp.PointOnLine2[0];
- lineRight.PointOnLine2.y := lineTemp.PointOnLine2[2];
- //Oben
- MakeEbene(Top);
- Intersect3D_2Planes(ebene,nullebene,lineTemp);
- lineTop.PointOnLine1.x := lineTemp.PointOnLine1[0];
- lineTop.PointOnLine1.y := lineTemp.PointOnLine1[2];
- lineTop.PointOnLine2.x := lineTemp.PointOnLine2[0];
- lineTop.PointOnLine2.y := lineTemp.PointOnLine2[2];
- //Unten
- MakeEbene(Bottom);
- Intersect3D_2Planes(ebene,nullebene,lineTemp);
- lineBottom.PointOnLine1.x := lineTemp.PointOnLine1[0];
- lineBottom.PointOnLine1.y := lineTemp.PointOnLine1[2];
- lineBottom.PointOnLine2.x := lineTemp.PointOnLine2[0];
- lineBottom.PointOnLine2.y := lineTemp.PointOnLine2[2];
- // Left-Bottom
- Intersect2D_2Lines(lineLeft,lineBottom,intersectLeftBottom);
- // Bottom-Right
- Intersect2D_2Lines(lineBottom,lineRight,intersectBottomRight);
- // Right-Top
- Intersect2D_2Lines(lineRight,lineTop,intersectRightTop);
- // Top-Left
- Intersect2D_2Lines(lineTop,lineLeft,intersectTopLeft);
- SetRoundMode(rmDown);
- minX := Round(SmallestValue(intersectLeftBottom.x,
- intersectBottomRight.x,
- intersectRightTop.x,
- intersectTopLeft.x));
- SetRoundMode(rmUp);
- maxX := Round(GreatestValue(intersectLeftBottom.x,
- intersectBottomRight.x,
- intersectRightTop.x,
- intersectTopLeft.x));
- SetRoundMode(rmDown);
- minY := Round(SmallestValue(intersectLeftBottom.y,
- intersectBottomRight.y,
- intersectRightTop.y,
- intersectTopLeft.y));
- SetRoundMode(rmUp);
- maxY := Round(GreatestValue(intersectLeftBottom.y,
- intersectBottomRight.y,
- intersectRightTop.y,
- intersectTopLeft.y));
- SetRoundMode(rmNearest);
- //...
- for i := minX to maxX do
- for j := minY to maxY do
- PunktZeichnen(i,j);
- end;