using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
namespace GIS.Geometry
{
/// <summary>
/// geometry functions used in Mapview.
/// </summary>
public class GeoUtil
{
public static double TrainagleArea(PointF p0,PointF p1,PointF p2)
{
return (p0.Y - p2.Y) * (p1.X - p2.X) - (p1.Y - p2.Y) * (p0.X - p2.X);
}
public static double SquareDistance(PointF p1,PointF p2)
{
double dx = p1.X-p2.X;
double dy = p1.Y-p2.Y;
return dx*dx+dy*dy;
}
public static double DistanceBetweenPointToSegment(PointF s0, PointF s1,PointF p)
{
double s1p_sqr = SquareDistance(s1, p );
double ps0_sqr = SquareDistance(p , s0);
double s0s1_sqr = SquareDistance(s0, s1);
if (s1p_sqr < s0s1_sqr)
{
if(s0s1_sqr < ps0_sqr)
{
// ps0_sqr s0s1_sqr s1p_sqr
if (s0s1_sqr + s1p_sqr <= ps0_sqr)
return s1p_sqr;
}
// s0s1_sqr (s1p_sqr, ps0_sqr)
if (s0s1_sqr <= s1p_sqr + ps0_sqr)
return Math.Min(s1p_sqr, ps0_sqr);
}
else
{
// s1p_sqr s0s1_sqr
if (s1p_sqr < ps0_sqr)
{
// ps0_sqr s1p_sqr s0s1_sqr
if (s1p_sqr + s0s1_sqr <= ps0_sqr)
return s1p_sqr;
}
else
{
// s1p_sqr (s0s1_sqr, ps0_sqr)
if (s0s1_sqr + ps0_sqr <= s1p_sqr)
return ps0_sqr;
}
}
double tri_area = TrainagleArea(s0, s1, p);
return tri_area*tri_area/s0s1_sqr;
}
public static LineObject PerpendicularLine(LineObject l)
{
//Returns the line perpendicular to l
// using the center of l as the first point
LineObject l0=new LineObject(0,0,0,0);
float deltax=0.0F;
float deltay=0.0F;
l0.x1=l.x1+l.x2/2.0F;
l0.y1=l.y1+l.y2/2.0F;
deltax=l0.x1-l.x1;
deltax=l0.y1-l.y1;
l0.x2=l0.x1+(-deltay);
l0.y2=l0.y1+(-deltax);
return l0;
}
public static int LineIntersect(LineObject l1, LineObject l2, PointF pt)
{
//Calculate the intersection point of any two give non-parallel lines
// Returns -1: Lines are parallel
// 0: Neither Line contains the intersection point on it.
// 1: Line1 contains the intersection point
// 2: Line2 contains the intersection point
// 3: Both lines contains the intersection point
// ** contains the intersection point
bool intersect=false;
int iret=0;
float denom=0.0F;
float pDelta1=0.0F;
float pDelta2=0.0F;
PointF[] delta=new PointF[2];
delta[0].X=l1.x1-l2.x1;
delta[0].Y=l1.y1-l2.y1;
delta[1].X=l1.x2-l1.x1;
delta[1].Y=l1.y2-l1.y1;
delta[2].X=l2.x2-l2.x1;
delta[2].Y=l2.y2-l2.y1;
denom=(delta[2].Y*delta[1].X)-(delta[2].X-delta[1].Y);
intersect =false;
if (denom!=0.0F)intersect =true;
if (intersect)
{
pDelta1=((delta[2].X*delta[0].Y)-(delta[2].Y*delta[0].X))/denom;
pDelta2=((delta[1].X*delta[0].Y)-(delta[1].Y*delta[0].X))/denom;
//iret=IsBetween(pDelta1,0.0F,1.0F)?1:0 | IsBetween(pDelta2,0.0F,1.0F)?1:0;
pt.X=l1.x1+(pDelta1*delta[1].X);
pt.Y=l1.y1+(pDelta1*delta[1].Y);
}
return iret;
}
public static float LineAngleInRadians(LineObject l1)
{
float delX,delY,angle;
delX=l1.x2-l1.x1;
delY=l1.y2-l1.y1;
if(delX==0)
{
if(delY<0)
{
angle=(float)Math.PI/2.0F;
}
else
{
angle=(float)Math.PI*1.5F;
}
}
else if (delY==0)
{
if(delX>=0)
{
angle=0.0F;
}
else
{
angle=(float)Math.PI;
}
}
else
{
angle=(float)Math.Atan(Math.Abs(delY/delX));
if(delX>=0 && delY>=0)
{
angle=((float)Math.PI*2.0F)-angle;
}
else if(delX<0 && delY>=0)
{
angle=(float)Math.PI+angle;
}
else if (delX<0 && delY<0)
{
angle=(float)Math.PI-angle;
}
}
return angle;
}
public static bool IsBetween(object obj1, object obj2)
{
return false;
}
public static float RadiansToDegrees(float rad)
{
return rad*180.0F/(float)Math.PI;
}
public static float DegreesToRadians(float deg)
{
return deg*(float)Math.PI/180.0F;
}
// ' Return the cross product AB x BC.
// ' The cross product is a vector perpendicular to AB
// ' and BC having length |AB| * |BC| * Sin(theta) and
// ' with direction given by the right-hand rule.
// ' For two vectors in the X-Y plane, the result is a
// ' vector with X and Y components 0 so the Z component
// ' gives the vector's length and direction.
public static float CrossProductLength(
float Ax,
float Ay,
float Bx,
float By,
float Cx,
float Cy )
{
float BAx;
float BAy;
float BCx;
float BCy;
// Get the vectors' coordinates.
BAx = Ax - Bx;
BAy = Ay - By;
BCx = Cx - Bx;
BCy = Cy - By;
// Calculate the Z coordinate of the cross product.
return BAx * BCy - BAy * BCx;
}
//' Return the dot product AB � BC.
//' Note that AB � BC = |AB| * |BC| * Cos(theta).
private static float DotProduct(
float Ax, float Ay,
float Bx, float By,
float Cx, float Cy )
{
float BAx;
float BAy;
float BCx;
float BCy;
// Get the vectors' coordinates.
BAx = Ax - Bx;
BAy = Ay - By;
BCx = Cx - Bx;
BCy = Cy - By;
// Calculate the dot product.
return BAx * BCx + BAy * BCy;
}
public static double GetAngle(float Ax, float Ay, float Bx, float By, float Cx, float Cy)
// ' Return the angle ABC.
// ' Return a value between PI and -PI.
// ' Note that the value is the opposite of what you might
// ' expect because Y coordinates increase downward.
{
float dot_product;
float cross_product;
// Get the dot product and cross product.
dot_product = DotProduct(Ax, Ay, Bx, By, Cx, Cy);
cross_product = CrossProductLength(Ax, Ay, Bx, By, Cx, Cy);
// Calculate the angle.
return Math.Atan2(cross_product, dot_product);
}
/// <summary>
/// Center an image on a screen distination rectangle so she could paint
/// keeping centering and ratio
/// </summary>
public static Rectangle ViewRatio(Rectangle src, Rectangle dst)
{
Rectangle rcResultatScreen = new Rectangle();
float fRatioX = (float)dst.Width/(float)src.Width;
float fRatioY = (float)dst.Height/(float)src.Height;
float fRatio = fRatioX;
if(fRatioY<fRatioX)
fRatio = fRatioY;
float fWidth = fRatio*src.Width;
float fHeight = fRatio*src.Height;
rcResultatScreen.X = dst.Left+(dst.Width-(int) fWidth)/2;
rcResultatScreen.Y = dst.Top+(dst.Height-(int) fHeight)/2;
rcResultatScreen.Width = (int) fWidth;
rcResultatScreen.Height = (int) fHeight;
return rcResultatScreen;
}
/// <summary>
// Apply the specific matrix to the rectangle which is always (0,0) based...
/// </summary>
static public Rectangle ApplyCenterMatrix(Rectangle in_RcROI, Matrix in_Matrix, Size in_szImg)
{
Rectangle rcRet = new Rectangle();
Point[] rcFPoint = new Point[2];
rcFPoint[0].X = in_RcROI.X;
rcFPoint[0].Y = in_RcROI.Y;
rcFPoint[1].X = in_RcROI.X+in_RcROI.Width;
rcFPoint[1].Y = in_RcROI.Y+in_RcROI.Height;
in_Matrix.TransformPoints(rcFPoint); // Apply basic matrix
// Rotate Image Size Too
Rectangle rcImg = new Rectangle(new Point(0,0), in_szImg);
Point[] RectPoint = RectToPoint(rcImg);
in_Matrix.TransformPoints(RectPoint); // Apply basic matrix
// Search Offst to place Origin point
Point MinPt = new Point(RectPoint[0].X, RectPoint[0].Y);
if(rcFPoint[0].X>RectPoint[1].X)
MinPt.X = RectPoint[1].X;
if(rcFPoint[0].Y>RectPoint[1].Y)
MinPt.Y = RectPoint[1].Y;
// Now apply Offset translatation to come back to non centered position
Matrix OffSetMatrix = new Matrix();
OffSetMatrix.Translate(-MinPt.X, -MinPt.Y, MatrixOrder.Append);
OffSetMatrix.TransformPoints(rcFPoint);
rcRet.X = Math.Min(rcFPoint[0].X, rcFPoint[1].X);
rcRet.Y = Math.Min(rcFPoint[0].Y, rcFPoint[1].Y);
rcRet.Width = Math.Abs(rcFPoint[1].X-rcFPoint[0].X);
rcRet.Height = Math.Abs(rcFPoint[1].Y-rcFPoint[0].Y);
return rcRet;
}
public static bool IsValid(Rectangle r)
{ bool v=false;
if (r.Width!=0 && r.Height!=0){v=true;}
return v;
}
public static bool IsValid(RectangleF r)
{ bool v=false;
if (r.Width!=0 && r.Height!=0){v=true;}
return v;
}
public static int Swap(ref PointF [] p0)
{
PointF p2=new PointF();
PointF p3=new PointF();
double w=p0[1].X-p0[0].X;
double h=p0[1].Y-p0[0].Y;
//Ist Quardrant
if (w>0 && h<0)
{
p3.X=p0[0].X;
p3.Y=p0[1].Y;
p2.X=p0[1].X;
p2.Y=p0[0].Y;
p0[0]=p3;
p0[1]=p2;
return 1;
}
///2nd Quadrant
else if (w<0 && h<0)
{
p3=p0[1];
p2=p0[0];
p0[0]=p3;
p0[1]=p2;
return 2;
}
///3rd Quadrant
else if(w<0 && h>0)
{
p3.X=p0[1].X;
p3.Y=p0[0].Y;
p2.X=p0[0].X;
p2.Y=p0[1].Y;
p0[0]=p3;
p0[1]=p2;
return 3;
}
///4th Quadrant
else
{
//do nothing
return 4;
}
}
/// <summary>
/// Create a matrix to move from one rectangle to another
/// </summary>
static public Matrix Swap(Rectangle src, Rectangle dest)
{
Point[] Point3 = new Point[3];
Point3[0].X = dest.X;
Point3[0].Y = dest.Y;
Point3[1].X = dest.X+dest.Width;
Point3[1].Y = dest.Y;
Point3[2].X = dest.X;
Point3[2].Y = dest.Y+dest.Height;
Matrix NewMatrix = new Matrix(src, Point3);
return NewMatrix;
}
static public Matrix Swap(RectangleF src, RectangleF dest)
{
PointF[] Point3 = new PointF[3];
Point3[0].X = dest.X;
Point3[0].Y = dest.Y;
Point3[1].X = dest.X+dest.Width;
Point3[1].Y = dest.Y;
Point3[2].X = dest.X;
Point3[2].Y = dest.Y+dest.Height;
Matrix NewMatrix = new Matrix(src, Point3);
return NewMatrix;
}
/// <summary>
/// Create an array of point from a single rectangle
/// </summary>
static public Point[] RectToPoint(Rectangle src)
{
Point[] Point2 = new Point[2];
Point2[0].X = src.X;
Point2[0].Y = src.Y;
Point2[1].X = src.X+src.Width;
Point2[1].Y = src.Y+src.Height;
return Point2;
}
}
}