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); }
//! 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 ); }