Convex hull for a simple quadrilatteral

This commit is contained in:
hkrish 2013-05-05 14:25:51 +02:00
parent 7075427619
commit f9bd295201

View file

@ -13,9 +13,9 @@ function runTests() {
// pathA.rotate( 45 );
pathB = new Path.Circle(new Point(160, 110), 50);
// pathB.rotate( 45 );
pathB.segments[3].point = pathB.segments[3].point.add( [10, -120] );
pathB.segments[0].handleIn = pathB.segments[0].handleIn.add( [-100, 0] );
// pathB.translate( [ 50, -20 ] );
// pathB.segments[3].point = pathB.segments[3].point.add( [10, -120] );
// pathB.segments[0].handleIn = pathB.segments[0].handleIn.add( [-100, 0] );
pathB.translate( [ -20, -10 ] );
// testIntersection( pathA, pathB, caption );
window.a = pathA;
@ -24,7 +24,7 @@ function runTests() {
var _p1U = new Path( pathA.segments[1], pathA.segments[2] );
// var _p1U = new Path( pathA.segments[1], pathA.segments[2] );
// _p1U.reverse();
var _p2U = new Path( pathB.segments[3], pathB.segments[0] );
var _p2U = new Path( pathB.segments[0], pathB.segments[1] );
_p1U.style = _p2U.style = pathStyleBoolean;
var crvs = _p2U.curves;
// for (var i = 0; i < crvs.length; i++) {
@ -32,13 +32,13 @@ function runTests() {
drawFatline( crvs[0].getValues() );
// }
var maxCount = 1000, count = maxCount, loc, loc2;
var maxCount = 1, count = maxCount, loc, loc2;
var v1 = crvs[0].getValues(), v2 = _p1U.curves[0].getValues();
console.time('fatline');
while( count-- ){
loc = [];
Curve.getIntersections2( v1, v2, crvs[0], _p1U.curves[0], loc );
// var ret = _clipFatLine( v2, v1, 0, 1, 0, 1, 1, 1, true, crvs[0], _p1U.curves[0], loc );
// Curve.getIntersections2( v1, v2, crvs[0], _p1U.curves[0], loc );
var ret = _clipFatLine( v1, v2, 0, 1, 0, 1, 1, 1, true, crvs[0], _p1U.curves[0], loc );
}
console.timeEnd('fatline');
@ -62,6 +62,9 @@ function runTests() {
console.log( 'paperjs t = ' + loc2[i].getIntersection().parameter );
}
convexhull( 20, 20 , 30 , -20 );
view.draw();
@ -140,6 +143,92 @@ function markIntersections( ixs ){
}
}
function convexhull( dq0, dq1, dq2, dq3 ){
// Prepare the convex hull for D(ti, di(t))
var distq1 = _getSignedDist( 0.0, dq0, 1.0, dq3, 0.3333333333333333, dq1 );
var distq2 = _getSignedDist( 0.0, dq0, 1.0, dq3, 0.6666666666666666, dq2 );
// Check if [1/3, dq1] and [2/3, dq2] are on the same side of line [0,dq0, 1,dq3]
if( distq1 * distq2 < 0 ) {
Dt = [
[ 0.0, dq0, 0.3333333333333333, dq1 ],
[ 0.3333333333333333, dq1, 1.0, dq3 ],
[ 0.6666666666666666, dq2, 0.0, dq0 ],
[ 1.0, dq3, 0.6666666666666666, dq2 ]
];
} else {
// Check if the hull is a triangle or a quadrilatteral
var dqmin, dqmax, dqapex1, dqapex2;
distq1 = Math.abs(distq1);
distq2 = Math.abs(distq2);
if( distq1 > distq2 ){
dqapex1 = dq3;
dqapex2 = dq0;
dqmin = [ 0.6666666666666666, dq2 ];
dqmax = [ 0.3333333333333333, dq1 ];
} else {
dqapex1 = dq0;
dqapex2 = dq3;
dqmin = [ 0.3333333333333333, dq1 ];
dqmax = [ 0.6666666666666666, dq2 ];
}
// vector dq3->dq0
var vq30x = 1.0, vq30y = dq3 - dq1;
// vector dq3->dqmax
var vq3Maxx = 1 - dqmax[0], vq3Maxy = dq3 - dqmax[1];
// vector dq3->dqmin
var vq3Minx = 1 - dqmin[0], vq3Miny = dq3 - dqmin[1];
// vector dq0->dq3
var vq03x = -vq30x, vq03y = -vq30y;
// vector dq0->dqmax
var vq0Maxx = -dqmax[0], vq0Maxy = dq0 - dqmax[1];
// vector dq0->dqmin
var vq0Minx = -dqmin[0], vq0Miny = dq0 - dqmin[1];
// compare cross products of these vectors to determine, if
// point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ]
var vcross303Max = vq30x * vq3Maxy - vq30y * vq3Maxx;
var vcross3Max3Min = vq3Maxx * vq3Miny - vq3Maxy * vq3Minx;
var vcross030Max = vq03x * vq0Maxy - vq03y * vq0Maxx;
var vcross0Max0Min = vq0Maxx * vq0Miny - vq0Maxy * vq0Minx;
if(( ( distq1 > distq2 ) && vcross303Max * vcross3Max3Min < 0) || (( distq1 <= distq2 ) && vcross030Max * vcross0Max0Min < 0)){
// Point [2/3, dq2] is inside the triangle and the convex hull is a triangle
Dt = [
[ 0.0, dq0, dqmax[0], dqmax[1] ],
[ dqmax[0], dqmax[1], 1.0, dq3 ],
[ 1.0, dq3, 0.0, dq0 ]
];
} else {
// Convexhull is a quadrilatteral and we need all lines in the correct order
Dt = [
[ 0.0, dq0, 0.3333333333333333, dq1 ],
[ 0.3333333333333333, dq1, 0.6666666666666666, dq2 ],
[ 0.6666666666666666, dq2, 1.0, dq3 ],
[ 1.0, dq3, 0.0, dq0 ]
];
}
}
Dt2 = [
[ 0.0, dq0, 0.3333333333333333, dq1 ],
[ 0.3333333333333333, dq1, 0.6666666666666666, dq2 ],
[ 0.6666666666666666, dq2, 1.0, dq3 ],
[ 1.0, dq3, 0.0, dq0 ]
];
var yscale = 2;
var x = 500, y = 110;
for (var i = 0; i < Dt.length; i++) {
var pth = new Path.Line( new Point( x + Dt[i][0] * 190, y + Dt[i][1] * yscale ),
new Point( x + Dt[i][2] * 190, y + Dt[i][3] * yscale ) );
pth.style.strokeColor = '#999';
}
var pnt = [];
for ( i = 0; i < Dt2.length; i++) {
pnt.push( new Point( x + Dt2[i][0] * 190, y + Dt2[i][1] * yscale ) );
markPoint( pnt[i], " " );
}
new Path( new Segment(pnt[0], null, pnt[1].subtract(pnt[0])), new Segment( pnt[3], pnt[2].subtract(pnt[3]), null ) ).style.strokeColor = '#f00';
return Dt;
}
// ==============================================================
// On screen debug helpers
function markPoint( pnt, t, c, tc, remove ) {