From ed6221e993a0bc2ce548d0a5fe13bb5bf8aaa00e Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Fri, 1 Apr 2011 16:13:34 +0000 Subject: [PATCH] Added TriangleTriangleIntersect2D function --- vcg/space/intersection2.h | 558 ++++++++++++++++++++------------------ 1 file changed, 298 insertions(+), 260 deletions(-) diff --git a/vcg/space/intersection2.h b/vcg/space/intersection2.h index eaea37fe..58ae7117 100644 --- a/vcg/space/intersection2.h +++ b/vcg/space/intersection2.h @@ -1,260 +1,298 @@ -/**************************************************************************** - * VCGLib o o * - * Visual and Computer Graphics Library o o * - * _ O _ * - * Copyright(C) 2004 \/)\/ * - * Visual Computing Lab /\/| * - * ISTI - Italian National Research Council | * - * \ * - * All rights reserved. * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * - * for more details. * - * * - ****************************************************************************/ -/**************************************************************************** - History - -$Log: not supported by cvs2svn $ -Revision 1.6 2007/05/08 12:11:58 pietroni -added circle-line intersection - - -****************************************************************************/ - - - -#ifndef __VCGLIB_INTERSECTION_2 -#define __VCGLIB_INTERSECTION_2 -#include -#include -#include -#include -#include -#include - - - - -namespace vcg { -/** \addtogroup space */ -/*@{*/ -/** - Function computing the intersection between couple of geometric primitives in - 2 dimension -*/ - -/// return true if the algle is convex (right rotation) -template - inline bool Convex(const Point2 & p0,const Point2 & p1,const Point2 & p2) -{ - const SCALAR_TYPE EPS= SCALAR_TYPE(1e-8); - return (((p0-p1)^(p2-p1))<=EPS); -} - -///return if exist the intersection point -///between 2 lines in a 2d plane -template -inline bool LineLineIntersection(const vcg::Line2 & l0, - const vcg::Line2 & l1, - Point2 &p) -{ - const SCALAR_TYPE Eps= SCALAR_TYPE(1e-8); - ///first line - SCALAR_TYPE x1=l0.Origin().X(); - SCALAR_TYPE y1=l0.Origin().Y(); - SCALAR_TYPE x2=x1+l0.Direction().X(); - SCALAR_TYPE y2=y1+l0.Direction().Y(); - - ///second line - SCALAR_TYPE x3=l1.Origin().X(); - SCALAR_TYPE y3=l1.Origin().Y(); - SCALAR_TYPE x4=x3+l1.Direction().X(); - SCALAR_TYPE y4=y3+l1.Direction().Y(); - - ///then find intersection - - ///denominator - SCALAR_TYPE den=((x1-x2)*(y3-y4))-((y1-y2)*(x3-x4)); - if (fabs(den) -inline bool RayLineIntersection(const vcg::Line2 & l, - const vcg::Ray2 & r, - Point2 &p) -{ - ///construct line from ray - vcg::Line2 l_test; - l_test.Set(r.Origin(),r.Direction()); - if (!LineLineIntersection(l,l_test,p)) - return false; - Point2 dir=p-r.Origin(); - dir.Normalize(); - return (dir*r.Direction()>0); -} - - -/// interseciton between point and triangle -template -inline bool RaySegmentIntersection(const vcg::Ray2 & r, - const vcg::Segment2 &seg, - Point2 &p_inters) -{ - ///first compute intersection between lines - vcg::Line2 line2; - line2.SetOrigin(seg.P0()); - vcg::Point2 dir=seg.P1()-seg.P0(); - dir.Normalize(); - line2.SetDirection(dir); - if(!RayLineIntersection(line2,r,p_inters)) - return false; - ///then test if intersection point is nearest - ///to both extremes then lenght of the segment - SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); - SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); - SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); - return ((d0 -inline bool LineSegmentIntersection(const vcg::Line2 & line, - const vcg::Segment2 &seg, - Point2 &p_inters) -{ - ///first compute intersection between lines - vcg::Line2 line2; - line2.SetOrigin(seg.P0()); - vcg::Point2 dir=seg.P1()-seg.P0(); - dir.Normalize(); - line2.SetDirection(dir); - if(!LineLineIntersection(line,line2,p_inters)) - return false; - ///then test if intersection point is nearest - ///to both extremes then lenght of the segment - SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); - SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); - SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); - return ((d0 -inline bool SegmentSegmentIntersection(const vcg::Segment2 &seg0, - const vcg::Segment2 &seg1, - Point2 &p_inters) -{ - vcg::Line2 l0,l1; - - l0.SetOrigin(seg0.P0()); - vcg::Point2 dir0=seg0.P1()-seg0.P0(); - dir0.Normalize(); - l0.SetDirection(dir0); - - l1.SetOrigin(seg1.P0()); - vcg::Point2 dir1=seg1.P1()-seg1.P0(); - dir1.Normalize(); - l1.SetDirection(dir1); - LineLineIntersection(l0,l1,p_inters); - SCALAR_TYPE len0=seg0.Length(); - SCALAR_TYPE len1=seg1.Length(); - SCALAR_TYPE d0=(seg0.P0()-p_inters).Norm(); - SCALAR_TYPE d1=(seg1.P0()-p_inters).Norm(); - - if ((d0>len0)||(d1>len1)) - return false; - - vcg::Point2 dir2=p_inters-seg0.P0(); - vcg::Point2 dir3=p_inters-seg1.P0(); - if (((dir2*dir0)<0)||((dir3*dir1)<0)) - return false; - - return true; - -} -/// interseciton between point and triangle -template - inline bool IsInsideTrianglePoint( const Triangle2 & t,const Point2 & p) -{ - Point2 p0=t.P0(0); - Point2 p1=t.P0(1); - Point2 p2=t.P0(2); - - ///first test with bounding box - vcg::Box2 b2d; - b2d.Add(p0); - b2d.Add(p1); - b2d.Add(p2); - if (!b2d.IsIn(p)) - return false; - - ///then text convex - if (!Convex(p0,p1,p2)) - std::swap >(p1,p2); - return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); - //return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); -} - -//intersection between a circle and a line -template - inline bool CircleLineIntersection(const vcg::Line2 & line, - const vcg::Point2 ¢er, - const ScalarType &radius, - vcg::Point2 &p0, - vcg::Point2 &p1) - { - ///translate with origin on the center - ScalarType x1,x2,y1,y2; - x1=line.Origin().X()-center.X(); - y1=line.Origin().Y()-center.Y(); - x2=x1+line.Direction().X(); - y2=y1+line.Direction().Y(); - - ScalarType dx,dy,dr,D,delta,sign; - dx=x2-x1; - dy=y2-y1; - dr=sqrt(dx*dx+dy*dy); - D=x1*y2-x2*y1; - delta=radius*radius*dr*dr-D*D; - if (dy>=0) - sign=1; - else - sign=-1; - - if (delta<0.000001) - return false;///no intersection - else - { - p0.X()=(D*dy+sign*dx*sqrt(delta))/dr*dr; - p0.Y()=(-D*dx+fabs(dy)*sqrt(delta))/dr*dr; - p1.X()=(D*dy-sign*dx*sqrt(delta))/dr*dr; - p1.Y()=(-D*dx-fabs(dy)*sqrt(delta))/dr*dr; - p0+=center; - p1+=center; - return true; - } - } -/*@}*/ -} // end namespace -#endif +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ +Revision 1.6 2007/05/08 12:11:58 pietroni +added circle-line intersection + + +****************************************************************************/ + + + +#ifndef __VCGLIB_INTERSECTION_2 +#define __VCGLIB_INTERSECTION_2 +#include +#include +#include +#include +#include +#include + + + + +namespace vcg { + /** \addtogroup space */ + /*@{*/ + /** + Function computing the intersection between couple of geometric primitives in + 2 dimension + */ + + /// return true if the algle is convex (right rotation) + template + inline bool Convex(const Point2 & p0,const Point2 & p1,const Point2 & p2) + { + const SCALAR_TYPE EPS= SCALAR_TYPE(1e-8); + return (((p0-p1)^(p2-p1))<=EPS); + } + + ///return if exist the intersection point + ///between 2 lines in a 2d plane + template + inline bool LineLineIntersection(const vcg::Line2 & l0, + const vcg::Line2 & l1, + Point2 &p) + { + const SCALAR_TYPE Eps= SCALAR_TYPE(1e-8); + ///first line + SCALAR_TYPE x1=l0.Origin().X(); + SCALAR_TYPE y1=l0.Origin().Y(); + SCALAR_TYPE x2=x1+l0.Direction().X(); + SCALAR_TYPE y2=y1+l0.Direction().Y(); + + ///second line + SCALAR_TYPE x3=l1.Origin().X(); + SCALAR_TYPE y3=l1.Origin().Y(); + SCALAR_TYPE x4=x3+l1.Direction().X(); + SCALAR_TYPE y4=y3+l1.Direction().Y(); + + ///then find intersection + + ///denominator + SCALAR_TYPE den=((x1-x2)*(y3-y4))-((y1-y2)*(x3-x4)); + if (fabs(den) + inline bool RayLineIntersection(const vcg::Line2 & l, + const vcg::Ray2 & r, + Point2 &p) + { + ///construct line from ray + vcg::Line2 l_test; + l_test.Set(r.Origin(),r.Direction()); + if (!LineLineIntersection(l,l_test,p)) + return false; + Point2 dir=p-r.Origin(); + dir.Normalize(); + return (dir*r.Direction()>0); + } + + + /// interseciton between point and triangle + template + inline bool RaySegmentIntersection(const vcg::Ray2 & r, + const vcg::Segment2 &seg, + Point2 &p_inters) + { + ///first compute intersection between lines + vcg::Line2 line2; + line2.SetOrigin(seg.P0()); + vcg::Point2 dir=seg.P1()-seg.P0(); + dir.Normalize(); + line2.SetDirection(dir); + if(!RayLineIntersection(line2,r,p_inters)) + return false; + ///then test if intersection point is nearest + ///to both extremes then lenght of the segment + SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); + SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); + SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); + return ((d0 + inline bool LineSegmentIntersection(const vcg::Line2 & line, + const vcg::Segment2 &seg, + Point2 &p_inters) + { + ///first compute intersection between lines + vcg::Line2 line2; + line2.SetOrigin(seg.P0()); + vcg::Point2 dir=seg.P1()-seg.P0(); + dir.Normalize(); + line2.SetDirection(dir); + if(!LineLineIntersection(line,line2,p_inters)) + return false; + ///then test if intersection point is nearest + ///to both extremes then lenght of the segment + SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); + SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); + SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); + return ((d0 + inline bool SegmentSegmentIntersection(const vcg::Segment2 &seg0, + const vcg::Segment2 &seg1, + Point2 &p_inters) + { + vcg::Line2 l0,l1; + + l0.SetOrigin(seg0.P0()); + vcg::Point2 dir0=seg0.P1()-seg0.P0(); + dir0.Normalize(); + l0.SetDirection(dir0); + + l1.SetOrigin(seg1.P0()); + vcg::Point2 dir1=seg1.P1()-seg1.P0(); + dir1.Normalize(); + l1.SetDirection(dir1); + LineLineIntersection(l0,l1,p_inters); + SCALAR_TYPE len0=seg0.Length(); + SCALAR_TYPE len1=seg1.Length(); + SCALAR_TYPE d0=(seg0.P0()-p_inters).Norm(); + SCALAR_TYPE d1=(seg1.P0()-p_inters).Norm(); + + if ((d0>len0)||(d1>len1)) + return false; + + vcg::Point2 dir2=p_inters-seg0.P0(); + vcg::Point2 dir3=p_inters-seg1.P0(); + if (((dir2*dir0)<0)||((dir3*dir1)<0)) + return false; + + return true; + + } + /// interseciton between point and triangle + template + inline bool IsInsideTrianglePoint( const Triangle2 & t,const Point2 & p) + { + Point2 p0=t.P0(0); + Point2 p1=t.P0(1); + Point2 p2=t.P0(2); + + ///first test with bounding box + vcg::Box2 b2d; + b2d.Add(p0); + b2d.Add(p1); + b2d.Add(p2); + if (!b2d.IsIn(p)) + return false; + + ///then text convex + if (!Convex(p0,p1,p2)) + std::swap >(p1,p2); + return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); + //return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); + } + + template + bool TriangleTriangleIntersect2D(const vcg::Triangle2 &tr0, + const vcg::Triangle2 &tr1) + { + ///test BBox Intersection + vcg::Box2 bbtr0; + bbtr0.Add(tr0.P(0)); + bbtr0.Add(tr0.P(1)); + bbtr0.Add(tr0.P(2)); + vcg::Box2 bbtr1; + bbtr1.Add(tr1.P(0)); + bbtr1.Add(tr1.P(1)); + bbtr1.Add(tr1.P(2)); + if (!bbtr0.Collide(bbtr1)) return false; + ///test vertex in face + for (int i=0;i<3;i++) + { + bool inside0=vcg::IsInsideTrianglePoint(tr0,tr1.P(i)); + bool inside1=vcg::IsInsideTrianglePoint(tr1,tr0.P(i)); + if (inside0 || inside1) return true; + } + ///test segment + ///to segment intersection + for (int i=0;i<3;i++) + { + for (int j=0;j<3;j++) + { + if (i>j) continue; + vcg::Segment2 seg0=vcg::Segment2(tr0.P(i),tr0.P((i+1)%3)); + vcg::Segment2 seg1=vcg::Segment2(tr1.P(j),tr1.P((j+1)%3)); + vcg::Point2 p_inters; + bool intersect=SegmentSegmentIntersection(seg0,seg1,p_inters); + if (intersect) return true; + } + } + return false; + } + + //intersection between a circle and a line + template + inline bool CircleLineIntersection(const vcg::Line2 & line, + const vcg::Point2 ¢er, + const ScalarType &radius, + vcg::Point2 &p0, + vcg::Point2 &p1) + { + ///translate with origin on the center + ScalarType x1,x2,y1,y2; + x1=line.Origin().X()-center.X(); + y1=line.Origin().Y()-center.Y(); + x2=x1+line.Direction().X(); + y2=y1+line.Direction().Y(); + + ScalarType dx,dy,dr,D,delta,sign; + dx=x2-x1; + dy=y2-y1; + dr=sqrt(dx*dx+dy*dy); + D=x1*y2-x2*y1; + delta=radius*radius*dr*dr-D*D; + if (dy>=0) + sign=1; + else + sign=-1; + + if (delta<0.000001) + return false;///no intersection + else + { + p0.X()=(D*dy+sign*dx*sqrt(delta))/dr*dr; + p0.Y()=(-D*dx+fabs(dy)*sqrt(delta))/dr*dr; + p1.X()=(D*dy-sign*dx*sqrt(delta))/dr*dr; + p1.Y()=(-D*dx-fabs(dy)*sqrt(delta))/dr*dr; + p0+=center; + p1+=center; + return true; + } + } + /*@}*/ +} // end namespace +#endif