bool operator()( const Point1& a, const Point2& b ) const
        {
            BOOST_CONCEPT_ASSERT((Point2DConcept<Point1>));
            BOOST_CONCEPT_ASSERT((Point2DConcept<Point2>));
            
            const vector_double_2d da = a - m_origin, db = b - m_origin;
            const double detb = exterior_product_area( m_reference, db );

            //! If v2 is along reference it is smallest.
            if( m_cmp.equals(detb, 0) && m_cmp.greater_than_or_equal(dot_product( db, m_reference ), 0) )
                return false;
            
            const double deta = exterior_product_area( m_reference, da );

            //! If v1 is along reference it is smallest.
            if( m_cmp.equals(deta, 0) && m_cmp.greater_than_or_equal(dot_product( da, m_reference ), 0) )
                return true;

            //! If detv1 and detv2 have the same sign, they are on the same side of reference and can be compared directly.
            if( m_cmp.greater_than_or_equal(deta * detb, 0) )
            {
                //! both on same side of reference: compare to each other
                return m_cmp.greater_than(exterior_product_area( da, db ), 0);
            }

            //! At this point one of the two detvX is negative. A negative detvX means a large angle WRT reference.
            //! If v1 is positive it must be smaller than v2, else the opposite must be true.
            return m_cmp.greater_than(deta, 0);
        }
Exemplo n.º 2
0
		//! Generate a new item to visit based on the adjacent triangle at index next.
		boost::optional<edge_item> prepare_adjacent_traversal( std::size_t next, const edge_item& item )
		{
			comparison_policy cmp( 0 );
			bool allAround = get<0>( item.lo ) == constants::infinity<coordinate_type>() && get<0>( item.hi ) == constants::negative_infinity<coordinate_type>();

			const std::size_t* fromIndices = m_mesh.get_triangle_indices( item.to );
			const std::size_t* toIndices = m_mesh.get_triangle_indices( next );
						
			std::size_t side = get_triangle_adjacent_side( fromIndices, toIndices );
			auto pointLo = m_mesh.get_triangle_vertices( item.to )[side];
			auto pointHi = m_mesh.get_triangle_vertices( item.to )[(side + 1) % 3];

			if( exterior_product_area( pointHi - pointLo, m_origin - pointLo ) < constants::zero<decltype(std::declval<coordinate_type>() * std::declval<coordinate_type>())>() )
				std::swap( pointLo, pointHi );

			if (!is_segment_in_range_2d(make_segment(pointLo, pointHi), item.lo, item.hi, m_origin)) 
				return boost::none;

#if GEOMETRIX_TEST_ENABLED(GEOMETRIX_DEBUG_VISIBLE_VERTICES_MESH_SEARCH)
			//polygon2 pTri(mMesh.get_triangle_vertices(item.from), mMesh.get_triangle_vertices(item.from) + 3);
			typedef std::vector<point_t> polygon2;
			typedef segment<point_t> segment2;
			polygon2 cTri(m_mesh.get_triangle_vertices(item.to), m_mesh.get_triangle_vertices(item.to) + 3);
			polygon2 nTri(m_mesh.get_triangle_vertices(next), m_mesh.get_triangle_vertices(next) + 3);
			segment2 sLo{ m_origin, m_origin + item.lo };
			segment2 sHi{ m_origin, m_origin + item.hi };
			segment2 cLo{ m_origin, pointLo };
			segment2 cHi{ m_origin, pointHi };
#endif

			vector_t vecLo, vecHi;
			if( !numeric_sequence_equals_2d(m_origin, pointLo, cmp) && !numeric_sequence_equals_2d(m_origin, pointHi, cmp) )
			{
				assign( vecLo, pointLo - m_origin );
				assign( vecHi, pointHi - m_origin );
				
				if (!allAround)
				{
					vecLo = is_vector_between(item.lo, item.hi, vecLo, false, cmp) ? vecLo : item.lo;
					vecHi = is_vector_between(item.lo, item.hi, vecHi, false, cmp) ? vecHi : item.hi;
				}

				if (get_orientation(vecHi, vecLo, cmp) == geometrix::oriented_left)
					return boost::none;
			}
			else
			{
				assign( vecLo, constants::infinity<coordinate_type>(), constants::zero<coordinate_type>() );
				assign( vecHi, constants::negative_infinity<coordinate_type>(), constants::zero<coordinate_type>() );
			}
			
#if GEOMETRIX_TEST_ENABLED(GEOMETRIX_DEBUG_VISIBLE_VERTICES_MESH_SEARCH)
			segment2 nLo{ m_origin, m_origin + vecLo };
			segment2 nHi{ m_origin, m_origin + vecHi };
#endif			
			return edge_item( item.to, next, vecLo, vecHi );
		}