Mini Kabibi Habibi
//
// Copyright 2006-2007, 2015 Adobe Systems, Incorporated. All Rights Reserved.
//
/*
@@@BUILDINFO@@@ Geometry.jsx 1.0.0.0
*/
//
// Geometry definitions, based on PMGeometry.h
//
function className( thing )
{
if ((typeof(thing) == "object") && (typeof(thing.className) != "undefined"))
return thing.className;
else
return typeof(thing);
}
//
// =================================== TPoint ===================================
//
function TPoint( x, y )
{
this.fX = x;
this.fY = y;
}
// TPoint Constants
const kTPointOrigion = new TPoint( 0, 0 );
TPoint.kOrigin = kTPointOrigion;
const kTPointInfinite = new TPoint( Infinity, Infinity );
TPoint.kInfinite = kTPointInfinite;
const kTPointClassname = "TPoint";
TPoint.prototype.className = kTPointClassname;
// Overloaded math operators
TPoint.prototype["=="] = function( Src )
{
return (this.fX == Src.fX) && (this.fY == Src.fY);
}
TPoint.prototype["==="] = function( Src )
{
return (this.fX === Src.fX) && (this.fY === Src.fY);
}
TPoint.prototype["+"] = function( b )
{
return new TPoint( this.fX + b.fX, this.fY + b.fY );
}
TPoint.prototype["-"] = function( b, reversed )
{
if (typeof(b) == "undefined") // unary minus
return new TPoint( -this.fX, -this.fY )
else
{
if (reversed)
return new TPoint( b.fX - this.fX, by.fY - this.fY );
else
return new TPoint( this.fX - b.fX, this.fY - b.fY);
}
}
//
// Multiply and divide work with scalars as well as points
//
TPoint.prototype["*"] = function( b )
{
if (typeof(b) == 'number')
return new TPoint( this.fX * b, this.fY * b );
else
return new TPoint( this.fX * b.fX, this.fY * b.fY );
}
TPoint.prototype["/"] = function( b, reversed )
{
if (reversed)
{
if (typeof(b) == "number")
debugger; // Can't divide a number by a point
else
return new TPoint( b.fX / this.fX, b.fY / this.fY );
}
else
{
if (typeof(b) == 'number')
return new TPoint( this.fX / b, this.fY / b );
else
return new TPoint( this.fX / b.fX, this.fY / b.fY );
}
}
TPoint.prototype.toString = function()
{
return "[" + this.fX.toString() + "," + this.fY.toString() + "]";
}
TPoint.prototype.vectorLength = function()
{
return Math.sqrt( this.fX * this.fX + this.fY * this.fY );
}
TPoint.prototype.distanceTo = function(p)
{
var delta = this - p;
return delta.vectorLength();
}
// Return normalized vector
TPoint.prototype.normalize = function()
{
var vecLen = this.vectorLength();
if (vecLen == 0.0)
return new TPoint( 0.0, 0.0 );
else
return new TPoint( this.fX / vecLen, this.fY / vecLen );
}
// Return the angle between the vector from the origin to this and the X axis
TPoint.prototype.vectorAngle = function()
{
var offset = 0.0;
if (this.fX == 0.0)
{
if (this.fY == 0.0)
return 0.0;
if (this.fY > 0.0)
return Math.PI / 2.0;
else
return 3 * (Math.PI/2);
}
else
{
if ((this.fX > 0.0) && (this.fY < 0.0))
offset = 2*Math.PI;
else
if (this.fX < 0.0)
offset = Math.PI;
return Math.atan( this.fY / this.fX ) + offset;
}
}
// Rotate point around angle (in radians) and return the rotated point.
TPoint.prototype.rotate = function( angle )
{
var ca = Math.cos(angle);
var sa = Math.sin(angle);
var nx = this.fX * ca - this.fY * sa;
var ny = this.fY * ca + this.fX * sa;
return new TPoint( nx, ny );
}
//
// Test to see if the point is in the quadrilateral (or any convex polygon)
// defined by four points by checking to see if it's on the same side of
// the four edges. Assumes points are in clockwise (or counterclockwise)
// order. This is from the classic "10 Algorithms" paper by Sutherland,
// et al.
//
TPoint.prototype.pointInQuad = function( pts )
{
var i = 0, j;
var inside = true;
var whichSide;
while ((i < pts.length) && inside)
{
j = (i == pts.length-1) ? 0 : i + 1;
var A = (this.fX - pts[j].fX) * (pts[i].fY - pts[j].fY);
var B = (this.fY - pts[j].fY) * (pts[i].fX - pts[j].fX);
if (i == 0)
whichSide = (A > B);
else
inside = (whichSide == (A > B));
i++;
}
return inside;
}
// Report what "side" of the line p0, p1 the point is on.
TPoint.prototype.sideOf = function( p0, p1 )
{
var dist = this.distanceToLine( p0, p1 );
if (dist == 0.0) return 0;
if (dist < 0.0) return -1;
return 1;
}
//
// Compute the distance from "this" to the line defined by p0, p1
//
TPoint.prototype.distanceToLine = function( p0, p1 )
{
var fBase = p0;
var fDirection = p1 - p0;
var other_base = this;
var other_dir = new TPoint( -fDirection.fY, fDirection.fX );
// Find point where line perpendicular to p0p1 through this intersects p0p1
var online = TPoint.lineSegmentIntersect( fBase, fDirection + fBase,
other_base, other_dir + other_base, false );
var fromDir = this - online;
var dist = fromDir.vectorLength();
// Determine the sign by comparing the vector signs between the
// point and the line and the line's perpendicular vector.
if (Math.abs( fromDir.fX ) > Math.abs( fromDir.fY ))
return (fromDir.fX * fDirection.fY <= 0.0) ? dist : -dist;
else
return (fromDir.fY * fDirection.fX > 0.0) ? dist : -dist;
};
// Find where (parametrically) test falls on the
// segment p10 p11. If it's beyond 0..1, there's no hit
TPoint.prototype.pointInSeg = function( p0, p1 )
{
// Find two vectors, p0p1 & p0test
var v0 = p1 - p0;
var vm = this - p0;
// Ratio of dot prodcuts gives the projection of vm onto v0
var t, denom = v0.fX * v0.fX + v0.fY * v0.fY;
if (denom == 0.0)
// First line seg zero length...
return (this == p0);
else
t = (v0.fX * vm.fX + v0.fY * vm.fY ) / denom;
return ((t >= 0.0) && (t <= 1.0));
}
// Class static methods
// Find where line segment (p10 p11) intersects (p20 p21).
// Returns [INF, INF] if no intersection (lines parallel)
TPoint.lineSegmentIntersect = function( p10, p11, p20, p21, checkEndpoints )
{
var A1, B1, C1, A2, B2, C2; // Line equations
var tmp;
var cross = new TPoint( Infinity, Infinity );
if (typeof(checkEndpoints) == "undefined")
checkEndpoints = true;
// Generate the line equations (Ax+By=C) of the
// vectors Perpendicular to center->endpoint lines.
A1 = p10.fY - p11.fY;
B1 = p11.fX - p10.fX;
C1 = A1 * p10.fX + B1 * p10.fY;
A2 = p20.fY - p21.fY;
B2 = p21.fX - p20.fX;
C2 = A2 * p20.fX + B2 * p20.fY;
// Find the intersection of above two lines by solving:
// [A1 B1] [x] = [C1]
// [A2 B2] [y] = [C2]
tmp = A1 * B2 - B1 * A2;
if (tmp == 0.0) // Parallel
return cross;
else
{
cross.fX = (B2 * C1 - B1 * C2) / tmp;
cross.fY = (A1 * C2 - A2 * C1) / tmp;
}
if (!checkEndpoints
|| (cross.pointInSeg( p10, p11 ) && cross.pointInSeg( p20, p21 )))
return cross;
else
return new TPoint( Infinity, Infinity );
}
// Clip the line segment defined by p0, p1 to rect (note the segment may be extended
// as well). Returns false of the line misses the rect
TPoint.clipLineToRect = function( rect, p0, p1 )
{
var fBase = p0;
var fDirection = p1 - p0;
var leftPt, topPt, rightPt, bottomPt;
var inPts = new Array();
var incount = 0;
function evaluateAtX( x )
{
if (fDirection.fX == 0.0) // no Y intercept...
{
if (x == fBase.fX)
return new TPoint( x, Infinity );
else
return new TPoint( Infinity, Infinity );
}
else
return new TPoint( x, (fDirection.fY / fDirection.fX) * (x - fBase.fX) + fBase.fY );
}
function evaluateAtY( y )
{
if (fDirection.fY == 0.0) // no X intercept...
{
if (y == fBase.fY)
return new TPoint( Infinity, y );
else
return new TPoint( Infinity, Infinity );
}
else
return new TPoint( (fDirection.fX / fDirection.fY) * (y - fBase.fY) + fBase.fX, y );
}
// If line has no direction, just use the base point
if (fDirection == TPoint.kOrigin)
{
if (rect.contains( fBase ))
{
p0 = fBase;
p1 = fBase;
return true;
}
else
return true; // "Line" is outside of rectangle
}
// Find the intercepts of the rectangle on the line
leftPt = evaluateAtX( rect.fLeft );
if ((leftPt.fY >= rect.fTop) && (leftPt.fY <= rect.fBottom))
inPts[incount++] = leftPt;
topPt = evaluateAtY( rect.fTop );
if ((topPt.fX >= rect.fLeft) && (topPt.fX <= rect.fRight))
inPts[incount++] = topPt;
rightPt = evaluateAtX( rect.fRight );
if ((rightPt.fY >= rect.fTop) && (rightPt.fY <= rect.fBottom))
inPts[incount++] = rightPt;
bottomPt = evaluateAtY( rect.fBottom );
if ((bottomPt.fX >= rect.fLeft) && (bottomPt.fX <= rect.fRight))
inPts[incount++] = bottomPt;
if (incount == 0)
return false; // Non intersection leaves line unmodified
$.bp( incount == 1); // This would be weird...
p0 = inPts[0];
if (incount == 2) // Normal case
p1 = inPts[1];
else // If line hits a corner, find two unique points
{
var i;
for (i = 1; (i < incount) && (inPts[i] == p0); i++) {};
$.bp( i >= incount );
p1 = inPts[i];
}
return true;
}
// Find the area of a convex polygon. Always returns
// positive value, so the order (counter/clockwise) doesn't matter.
// From Mathworld: http://mathworld.wolfram.com/PolygonArea.html
TPoint.polygonArea = function( pts )
{
var i, sum = 0;
var n = pts.length-1;
for (i = 0; i < n; ++i)
sum += pts[i].fX*pts[i+1].fY - pts[i+1].fX * pts[i].fY;
sum += pts[n].fX*pts[0].fY - pts[0].fX * pts[n].fY;
return Math.abs(sum) * 0.5;
}
//
// =================================== TRect ===================================
//
function TRect( leftTop, rightBottom )
{
// Four arguments are assumed to be left top right bottom
if (arguments.length == 4)
{
this.fLeft = arguments[0];
this.fTop = arguments[1];
this.fRight = arguments[2];
this.fBottom = arguments[3];
}
else
// One argument is assumed to be a list of points; the bounds is returned
if ((arguments.length == 1))
{
this.setToBoundsOf( arguments[0] );
}
else
{
this.fLeft = leftTop.fX;
this.fTop = leftTop.fY;
this.fRight = rightBottom.fX;
this.fBottom = rightBottom.fY;
}
}
// TRect constants
const kZeroRectData = new TRect( 0, 0, 0, 0 );
TRect.kZeroRect = kZeroRectData;
const kInfiniteRectdata = new TRect( -Infinity, -Infinity, Infinity, Infinity );
TRect.kInfiniteRect = kInfiniteRectdata;
const kRectClassname = "TRect"
TRect.prototype.className = kRectClassname;
// Data access
TRect.prototype.getTopLeft = function()
{
return new TPoint( this.fLeft, this.fTop );
}
TRect.prototype.getBottomRight = function()
{
return new TPoint( this.fRight, this.fBottom );
}
TRect.prototype.getBottomLeft = function()
{
return new TPoint(this.fLeft, this.fBottom);
}
TRect.prototype.getTopRight = function()
{
return new TPoint(this.fRight, this.fTop);
}
// Return the four corner points of the rectangle as an array of points
TRect.prototype.getCornerPoints = function()
{
return [this.getTopLeft(), this.getTopRight(), this.getBottomRight(), this.getBottomLeft()];
}
// Returns true if (fRight > fLeft) && (fBottom > fTop)
TRect.prototype.isEmpty = function()
{
return (this.fLeft >= this.fRight) || (this.fTop >= this.fBottom);
}
// Returns true if no coordinates are infinite and left/right and top/bottom aren't crossed.
TRect.prototype.isValid = function()
{
if ((this.fLeft == Infinity) || (this.fRight == Infinity)
|| (this.fTop == Infinity) || (this.fBottom == Infinity))
return false;
return (this.fLeft <= this.fRight) && (this.fTop <= this.fBottom);
}
TRect.prototype.getSize = function()
{
return new TPoint( this.fRight-this.fLeft, this.fBottom-this.fTop );
}
TRect.prototype.getWidth = function()
{
return this.fRight - this.fLeft;
}
TRect.prototype.getHeight = function()
{
return this.fBottom-this.fTop;
}
TRect.prototype.getArea = function()
{
return this.getWidth() * this.getHeight();
}
TRect.prototype.contains = function( geometry )
{
if (className( geometry ) == "TPoint") // Check for point
{
var p = geometry;
return ((p.fX >= this.fLeft) &&
(p.fX < this.fRight) &&
(p.fY >= this.fTop) &&
(p.fY < this.fBottom));
}
else
{
var r = geometry; // Assume rect instead
return ((r.fLeft >= this.fLeft) &&
(r.fRight <= this.fRight) &&
(r.fTop >= this.fTop) &&
(r.fBottom <= this.fBottom));
}
}
// Modifiers
TRect.prototype.setToPoint = function( point )
{
this.fLeft = point.fX;
this.fTop = point.fY;
this.fRight = point.fX;;
this.fBottom = point.fY;
}
TRect.prototype.setTopLeft = function( point )
{
this.fLeft = point.fX;
this.fTop = point.fY;
}
TRect.prototype.setTopRight = function( point )
{
this.fRight = point.fX;
this.fTop = point.fY;
}
TRect.prototype.setBottomRight = function( point )
{
this.fRight = point.fX;;
this.fBottom = point.fY;
}
TRect.prototype.setBottomLeft = function( point )
{
this.fLeft = point.fX;;
this.fBottom = point.fY;
}
TRect.prototype.setSize = function( size )
{
this.fRight = this.fLeft + size.fX;
this.fBottom = this.fTop + size.fY;
}
TRect.prototype.setCenter = function( center )
{
var delta = center - this.getCenter();
this.fLeft += delta.fX;
this.fRight += delta.fX;
this.fTop += delta.fY;
this.fBottom += delta.fY;
}
TRect.prototype.setToBoundsOf = function( pointList )
{
this.fLeft = pointList[0].fX;
this.fTop = pointList[0].fY;
this.fRight = this.fLeft;
this.fBottom = this.fTop;
var i;
for (i = 1; i < pointList.length; i++)
this.extendTo( pointList[i] );
}
// Constructor version of above
TRect.getBounds = function( pointList )
{
var bounds = new TRect(pointList[0].fX, pointList[0].fY);
bounds.setToBoundsOf( pointList );
return bounds;
}
TRect.prototype.extendTo = function( geometry )
{
// Check incoming geometry for type...
if (className(geometry) == "TPoint")
{
var p = geometry;
if (p.fX < this.fLeft) this.fLeft = p.fX;
if (p.fY < this.fTop) this.fTop = p.fY;
if (p.fX > this.fRight) this.fRight = p.fX;
if (p.fY > this.fBottom) this.fBottom = p.fY;
}
else // Not point, assume rectangle
{
var r = geometry;
if (this.isEmpty())
{
this.fTop = r.fTop;
this.fLeft = r.fLeft;
this.fRight = r.fRight;
this.fBottom = r.fBottom;
}
else
{
if (! r.isEmpty())
{
if (r.fLeft < this.fLeft) this.fLeft = r.fLeft;
if (r.fTop < this.fTop) this.fTop = r.fTop;
if (r.fRight > this.fRight) this.fRight = r.fRight;
if (r.fBottom > this.fBottom) this.fBottom = r.fBottom;
}
}
}
}
TRect.prototype.intersectWith = function( r )
{
if (this.isEmpty() || r.isEmpty())
{
this.fLeft = this.fRight;
this.fTop = this.fBottom;
}
else
{
if (r.fLeft > this.fLeft) this.fLeft = r.fLeft;
if (r.fTop > this.fTop) this.fTop = r.fTop;
if (r.fRight < this.fRight) this.fRight = r.fRight;
if (r.fBottom < this.fBottom) this.fBottom = r.fBottom;
// If the two don't overlap, avoid an invalid rect
if (this.fRight < this.fLeft)
this.fLeft = this.fRight;
if (this.fBottom < this.fTop)
this.fTop = this.fBottom;
}
}
// "static" class member. Returns a new, distinct rectangle.
TRect.intersection = function( a, b )
{
var x = new TRect( a.fLeft, a.fTop, a.fRight, a.fBottom );
x.intersectWith( b );
return x;
}
TRect.prototype.intersects = function( r )
{
var result;
if (this.isEmpty())
result = false;
else if (r.isEmpty())
result = false;
else
result = ( (this.fLeft < r.fRight) && (this.fRight > r.fLeft) &&
(this.fTop < r.fBottom) && (this.fBottom > r.fTop) );
return result;
}
TRect.prototype.getCenter = function()
{
return new TPoint( (this.fLeft + this.fRight) * 0.5,
(this.fTop + this.fBottom) * 0.5 );
}
TRect.prototype.equalSize = function( r )
{
return ( ((this.fRight - this.fLeft) == (r.fRight - r.fLeft)) &&
((this.fBottom - this.fTop) == (r.fBottom - r.fTop)) );
}
TRect.prototype.offset = function( dg )
{
this.fLeft += dg.fX;
this.fTop += dg.fY;
this.fRight += dg.fX;
this.fBottom += dg.fY;
}
TRect.prototype.inset = function( inset )
{
this.fLeft += inset.fX;
this.fTop += inset.fY;
this.fRight -= inset.fX;
this.fBottom -= inset.fY;
}
TRect.prototype.pin = function( pt )
{
if (this.fLeft > this.fRight) pt.fX = (this.fLeft + this.fRight) / 2;
else if (pt.fX < this.fLeft) pt.fX = this.fLeft;
else if (pt.fX > this.fRight) pt.fX = this.fRight;
if (this.fTop > this.fBottom) pt.fY = (this.fTop + this.fBottom) / 2;
else if (pt.fY < this.fTop) pt.fY = this.fTop;
else if (pt.fY > this.fBottom) pt.fY = this.fBottom;
}
// Takes the r's size and position relative to the object's rectangle and
// maps it to the same size and position (proportionally) to the dest
// rectangle. If the source rectangle has a height or width of zero
// the rectangle r will have a corresponding infinite height or width.
TRect.prototype.mapRect = function( r, dest )
{
var victLT = new TPoint( r.fLeft, r.fTop );
var victRB = new TPoint( r.fRight, r.fBottom );
var srcLT = new TPoint( this.fLeft, this.fTop );
var srcRB = new TPoint( this.fRight, this.fBottom );
var destLT = new TPoint( dest.fLeft, dest.fTop );
var destRB = new TPoint( dest.fRight, dest.fBottom );
victLT -= srcLT;
victRB -= srcLT;
// bk bug fix - we need to use floating, rather than integer, arithmetic for scaling to work correctly.
// TPoint scale = (destRB - destLT) / (srcRB - srcLT);
// victLT *= scale;
// victRB *= scale;
var x_scale = (destRB.fX - destLT.fX) / (srcRB.fX - srcLT.fX);
var y_scale = (destRB.fY - destLT.fY) / (srcRB.fY - srcLT.fY);
victLT.fX = (victLT.fX * x_scale);
victLT.fY = (victLT.fY * y_scale);
victRB.fX = (victRB.fX * x_scale);
victRB.fY = (victRB.fY * y_scale);
victLT += destLT;
victRB += destLT;
return new TRect( victLT, victRB );
}
TRect.prototype.mapPoint = function( pt, dest )
{
var srcLT = new TPoint( this.fLeft, this.fTop );
var srcRB = new TPoint( this.fRight, this.fBottom );
var destLT = new TPoint( dest.fLeft, dest.fTop );
var destRB = new TPoint( dest.fRight, dest.fBottom );
pt -= srcLT;
var x_scale = (destRB.fX - destLT.fX) / (srcRB.fX - srcLT.fX);
var y_scale = (destRB.fY - destLT.fY) / (srcRB.fY - srcLT.fY);
pt.fX = (pt.fX * x_scale);
pt.fY = (pt.fY * y_scale);
pt += destLT;
return pt;
}
TRect.prototype.orderPoints = function()
{
if (this.fLeft > this.fRight)
{
var tmp = this.fRight;
this.fRight = this.fLeft;
this.fLeft = tmp;
}
if (this.fTop > this.fBottom)
{
var tmp = this.fTop;
this.fTop = this.fBottom;
this.fBottom = tmp;
}
}
TRect.prototype["=="] = function( src )
{
if (this.fLeft != src.fLeft) return false;
if (this.fTop != src.fTop) return false;
if (this.fRight != src.fRight) return false;
if (this.fBottom != src.fBottom) return false;
return true;
}
TRect.prototype.toString = function()
{
return "[" + this.fLeft.toString() + "," + this.fTop.toString()
+ "," + this.fRight.toString() + "," + this.fBottom.toString() + "]";
}
//
// Rectangle to rectangle clip, specialized for the
// crop case of removing the image rect from the crop rect,
// leaving behind the portions to be filled.
//
// OK, imagine 'minus' is completely inside of 'this'. That
// leaves eight possible leftover rectangle pieces; fewer
// if minus is not completely contained. We find these rects,
// (called "tiles" here) and coalesce them together as possible.
// For example, if minus is taller (both above & below) thisRect,
// then only rects 0,3,5 and 2,4,7 are left over.
//
// +---+---------+---+
// | 0 | 1 | 2 |
// +---+---------+---+
// | 3 | minus | 4 |
// +---+---------+---+
// | 5 | 6 | 7 |
// +---+---------+---+
//
// AdobePatentID="P5923-US"
TRect.prototype.subtract = function( minus )
{
if (minus.contains( this ) || !minus.intersects( this ))
return null;
var self = this;
var topLT = this.fTop < minus.fTop;
var leftLT = this.fLeft < minus.fLeft;
var rightGT = this.fRight > minus.fRight;
var bottomGT = this.fBottom > minus.fBottom;
// Figure out which tiles are visible
var tileState = [leftLT && topLT, topLT, rightGT && topLT, // 0, 1, 2
leftLT, rightGT, // 3 4
leftLT && bottomGT, bottomGT, rightGT && bottomGT]; // 5, 6, 7
var tileUsed = [false, false, false, false, false, false, false, false];
var resultRects = [];
// If a corner tile next to a side tile is visible, expand
// tileRect to include it.
function extendRect( tileRect, tileNum, side )
{
if (tileState[tileNum] && !tileUsed[tileNum])
{
tileUsed[tileNum] = true;
tileRect[side] = self[side];
}
}
// Check each of the "side" tiles, (1, 3, 4, 6). For each one,
// see if the adjacent tile is also included, and has not been
// used yet. If so, expand the returned rect for that side tile
// to include the neighbor.
function makeAndExpandSide( sideNum, thisSide, thisDst,
c1Num, c1Side, c2Num, c2Side )
{
if (tileState[sideNum])
{
tileUsed[sideNum] = true;
var newTile = new TRect( minus.fLeft, minus.fTop,
minus.fRight, minus.fBottom );
newTile[thisSide] = self[thisSide];
newTile[thisDst] = minus[thisSide];
// If either the c1 or c2 side isn't included, then
// shrink the new tile to this's corresponding side
if (! tileState[c1Num]) newTile[c1Side] = self[c1Side];
if (! tileState[c2Num]) newTile[c2Side] = self[c2Side];
extendRect( newTile, c1Num, c1Side );
extendRect( newTile, c2Num, c2Side );
resultRects.push( newTile );
}
}
// Walk around the edges, collecting and coalescing all the tiles we find.
makeAndExpandSide( 1, "fTop", "fBottom", 0, "fLeft", 2, "fRight" );
makeAndExpandSide( 3, "fLeft", "fRight", 0, "fTop", 5, "fBottom" );
makeAndExpandSide( 4, "fRight", "fLeft", 2, "fTop", 7, "fBottom" );
makeAndExpandSide( 6, "fBottom", "fTop", 5, "fLeft", 7, "fRight" );
return resultRects;
};
// DEBUG
//aa = new TPoint(2,3);
//bb = new TPoint(7,7);
//r = new TRect(0,0,2,2);
//t0 = new TPoint(2,7);
//t1 = new TPoint(6,3);
//p0 = new TPoint(2,3);
//p1 = new TPoint(6,7);