14#include "arcane/utils/Array.h"
15#include "arcane/utils/Real3.h"
16#include "arcane/utils/StringBuilder.h"
17#include "arcane/utils/TraceAccessor.h"
18#include "arcane/utils/NotImplementedException.h"
20#include "arcane/ISubDomain.h"
21#include "arcane/IMesh.h"
22#include "arcane/IItemFamily.h"
23#include "arcane/Item.h"
24#include "arcane/BasicService.h"
25#include "arcane/FactoryService.h"
26#include "arcane/ItemPrinter.h"
27#include "arcane/ItemGroup.h"
28#include "arcane/VariableTypes.h"
29#include "arcane/IRayMeshIntersection.h"
30#include "arcane/IParallelMng.h"
31#include "arcane/IParticleFamily.h"
33#include "arcane_packages.h"
35#ifdef ARCANE_HAS_PACKAGE_LIMA
36#include <Lima/lima++.h>
37#define GLOBAL_HAS_LIMA true
39#define GLOBAL_HAS_LIMA false
47const bool global_has_lima = GLOBAL_HAS_LIMA;
81 m_rays_origin = origins;
82 m_rays_direction = directions;
93 m_triangles_coordinates = coordinates;
94 m_triangles_indexes = indexes;
125 return m_intersected_triangle_indexes;
153 Integer nb_ray = m_rays_origin.
size();
154 m_distances.
resize(nb_ray);
155 m_distances.
fill(1.0e100);
156 m_intersected_triangle_indexes.
resize(nb_ray);
157 m_intersected_triangle_indexes.
fill(-1);
158 Integer nb_index = m_triangles_indexes.
size();
161 Integer nb_triangle = nb_index / 3;
162 info() <<
"COMPUTE RAY INTERSECTION nb_ray=" << nb_ray
163 <<
" nb_triangle=" << nb_triangle;
165 for( Integer i=0; i<nb_triangle; ++i ){
166 Real3 p0 = m_triangles_coordinates[m_triangles_indexes[(i*3)]];
167 Real3 p1 = m_triangles_coordinates[m_triangles_indexes[(i*3)+1]];
168 Real3 p2 = m_triangles_coordinates[m_triangles_indexes[(i*3)+2]];
169 _compute2(i,p0,p1,p2);
172 for( Integer i=0; i<nb_ray; ++i ){
173 Int32 tid = m_intersected_triangle_indexes[i];
175 m_distances[i] = -1.0;
182void RayTriangle3DIntersection::
185 Integer nb_ray = m_rays_origin.
size();
186 for( Integer i=0; i<nb_ray; ++i ){
189 info() <<
"Segment " << i <<
" intersect triangle " << triangle_id <<
" T=" << t;
190 if (t<m_distances[i]){
192 m_intersected_triangle_indexes[i] = triangle_id;
193 info() <<
"Get this triangle";
234 Real ZERO_TOLERANCE = 1.0e-14;
236 Real3 kDiff = origin - p0;
237 Real3 kEdge1 = p1 - p0;
238 Real3 kEdge2 = p2 - p0;
241 Real fDdN =
math::dot(direction,kNormal);
243 if (fDdN > ZERO_TOLERANCE)
247 else if (fDdN < -ZERO_TOLERANCE)
260 if (fDdQxE2 >= (Real)0.0)
263 if (fDdE1xQ >= (Real)0.0)
265 Real diff = fDdN-(fDdQxE2 + fDdE1xQ);
271 if (diff>=0.0 || diff>-ZERO_TOLERANCE)
274 Real fQdN = -fSign*
math::dot(kDiff,kNormal);
279 Real fExtDdN = m_pkSegment->Extent*fDdN;
280 if (-fExtDdN <= fQdN && fQdN <= fExtDdN)
286 Real fInv = ((Real)1.0)/fDdN;
310bool RayTriangle3DIntersection::
313 Real3 box_center = (box_max+box_min) * 0.5;
314 Real afWdU[3], afAWdU[3], afDdU[3], afADdU[3], afAWxDdU[3], fRhs;
316 Real3 kDiff = origin - box_center;
321 Axis[0] =
Real3(1.0,0.0,0.0);
322 Axis[1] =
Real3(0.0,1.0,0.0);
323 Axis[2] =
Real3(0.0,0.0,1.0);
325 Extent[0] = box_max.
x - box_min.
x;
326 Extent[1] = box_max.
y - box_min.
y;
327 Extent[2] = box_max.
z - box_min.
z;
330 afAWdU[0] = math::abs(afWdU[0]);
332 afADdU[0] = math::abs(afDdU[0]);
333 if (afADdU[0] > Extent[0] && afDdU[0]*afWdU[0] >= (Real)0.0)
339 afAWdU[1] = math::abs(afWdU[1]);
341 afADdU[1] = math::abs(afDdU[1]);
342 if (afADdU[1] > Extent[1] && afDdU[1]*afWdU[1] >= (Real)0.0)
348 afAWdU[2] = math::abs(afWdU[2]);
350 afADdU[2] = math::abs(afDdU[2]);
351 if (afADdU[2] > Extent[2] && afDdU[2]*afWdU[2] >= (Real)0.0)
358 afAWxDdU[0] = math::abs(
math::dot(kWxD,Axis[0]));
359 fRhs = Extent[1]*afAWdU[2] + Extent[2]*afAWdU[1];
360 if (afAWxDdU[0] > fRhs)
365 afAWxDdU[1] = math::abs(
math::dot(kWxD,Axis[1]));
366 fRhs = Extent[0]*afAWdU[2] + Extent[2]*afAWdU[0];
367 if (afAWxDdU[1] > fRhs)
372 afAWxDdU[2] = math::abs(
math::dot(kWxD,Axis[2]));
373 fRhs = Extent[0]*afAWdU[1] + Extent[1]*afAWdU[0];
374 if (afAWxDdU[2] > fRhs)
390 : m_triangle_intersector(tm)
395 Int32 orig_face_local_id,
399 Real* distance,
Real3* position)
401 ARCANE_UNUSED(orig_face_local_id);
402 ARCANE_UNUSED(face_local_id);
404 Integer nb_node = face_nodes.
size();
408 Real3 center = (face_nodes[0] + face_nodes[1] + face_nodes[2] + face_nodes[3]) / 4.0;
409 Real d0 = m_triangle_intersector.
checkIntersection(origin,direction,center,face_nodes[0],face_nodes[1]);
410 Real d1 = m_triangle_intersector.
checkIntersection(origin,direction,center,face_nodes[1],face_nodes[2]);
411 Real d2 = m_triangle_intersector.
checkIntersection(origin,direction,center,face_nodes[2],face_nodes[3]);
412 Real d3 = m_triangle_intersector.
checkIntersection(origin,direction,center,face_nodes[3],face_nodes[0]);
415 if (d0>=0.0 && d0<d){
419 if (d1>=0.0 && d1<d){
423 if (d2>=0.0 && d2<d){
427 if (d3>=0.0 && d3<d){
434 *position = origin + d * direction;
483 m_face_intersector = intersector;
487 return m_face_intersector;
492 inline void _checkBoundingBox(
Real3 p,
Real3* ARCANE_RESTRICT min_bounding_box,
493 Real3* ARCANE_RESTRICT max_bounding_box)
495 if (p.
x<min_bounding_box->x)
496 min_bounding_box->x = p.
x;
497 if (p.
y<min_bounding_box->y)
498 min_bounding_box->y = p.
y;
499 if (p.
z<min_bounding_box->z)
500 min_bounding_box->z = p.
z;
502 if (p.
x>max_bounding_box->x)
503 max_bounding_box->x = p.
x;
504 if (p.
y>max_bounding_box->y)
505 max_bounding_box->y = p.
y;
506 if (p.
z>max_bounding_box->z)
507 max_bounding_box->z = p.
z;
510 void _writeSegments(Int32 rank,
515 IRayFaceIntersector* m_face_intersector;
521BasicRayMeshIntersection::
522BasicRayMeshIntersection(
const ServiceBuildInfo& sbi)
524, m_face_intersector(0)
540 IMesh* mesh = this->mesh();
543 info() <<
"COMPUTE INTERSECTION!!";
545 Integer nb_face = outer_faces.
size();
546 Integer nb_segment = segments_position.
size();
547 info() <<
"NB OUTER FACE=" << nb_face <<
" NB_SEGMENT=" << nb_segment;
549 const Real max_value = 1.0e100;
550 const Real3 max_bb(max_value,max_value,max_value);
551 const Real3 min_bb(-max_value,-max_value,-max_value);
553 Real3 mesh_min_bounding_box(max_bb);
554 Real3 mesh_max_bounding_box(min_bb);
562 Int32 lid = iface.localId();
563 Real3 face_max_bb(max_bb);
564 Real3 face_min_bb(min_bb);
565 for(
NodeEnumerator inode((*iface).nodes()); inode.hasNext(); ++inode )
566 _checkBoundingBox(nodes_coordinates[inode],&face_min_bb,&face_max_bb);
567 _checkBoundingBox(face_min_bb,&mesh_min_bounding_box,&mesh_max_bounding_box);
568 _checkBoundingBox(face_max_bb,&mesh_min_bounding_box,&mesh_max_bounding_box);
571 faces_min_bb[lid] = face_min_bb;
572 faces_max_bb[lid] = face_max_bb;
577 segments_distance.
fill(max_value);
578 faces_local_id.
fill(NULL_ITEM_LOCAL_ID);
580 if (!m_face_intersector)
584 for( Integer i=0; i<nb_segment; ++i ){
585 Real3 position = segments_position[i];
586 Real3 direction = segments_direction[i];
587 Int32 orig_face_local_id = segments_orig_face[i];
589 Real distance = 1.0e100;
590 Int32 min_face_local_id = NULL_ITEM_LOCAL_ID;
591 Int32 user_value = 0;
593 const Face& face = *iface;
602 is_bb = RayTriangle3DIntersection::checkBoundingBox(position,direction,faces_min_bb[lid],faces_max_bb[lid]);
605 Integer nb_node = face.
nbNode();
606 face_nodes.
resize(nb_node);
608 face_nodes[inode.index()] = nodes_coordinates[inode];
610 Real3 local_intersection;
612 bool is_found = m_face_intersector->
computeIntersection(position,direction,orig_face_local_id,lid,
613 face_nodes,&uv,&d,&local_intersection);
620 if (is_found && !is_bb)
621 fatal() <<
"Intersection found but no bounding box intersection";
622 if (is_found && d<distance){
624 min_face_local_id = lid;
625 intersection = local_intersection;
629 if (min_face_local_id==NULL_ITEM_LOCAL_ID)
631 segments_distance[i] = distance;
632 segments_intersection[i] = intersection;
633 faces_local_id[i] = min_face_local_id;
634 user_values[i] = user_value;
644 Int32 orig_face_local_id;
675 Integer global_nb_ray = pm->
reduce(Parallel::ReduceSum,nb_local_ray);
676 if (global_nb_ray==0)
678 info() <<
"LOCAL_NB_RAY=" << nb_local_ray <<
" GLOBAL=" << global_nb_ray;
687 Integer index = iitem.index();
690 local_positions[index] = rays_position[iitem];
691 local_directions[index] = rays_direction[iitem];
699 Integer index = iitem.index();
700 local_ids[index] = iitem.localId();
701 unique_ids[index] = (*iitem).uniqueId();
712 local_owners.
fill(my_rank);
727 for( Integer z=0, zn=all_orig_faces.
size(); z<zn; ++z ){
728 if (all_owners[z]!=my_rank)
729 all_orig_faces[z] = NULL_ITEM_LOCAL_ID;
731 compute(all_positions,all_directions,all_orig_faces,all_user_values,all_intersections,all_distances,all_faces);
741 for( Integer i=0; i<global_nb_ray; ++i ){
742 Int32 face_lid = all_faces[i];
743 if (face_lid==NULL_ITEM_LOCAL_ID)
746 fi.contrib_owner = my_rank;
747 fi.owner = all_owners[i];
748 fi.local_id = all_local_ids[i];
749 fi.face_local_id = all_faces[i];
750 fi.orig_face_local_id = all_orig_faces[i];
751 fi.user_value = all_user_values[i];
752 fi.intersection = all_intersections[i];
753 fi.distance = all_distances[i];
756 info() <<
"NB_FOUND=" << founds_info.
size();
764 Integer nb_total_found = global_founds_info.
size();
766 rays_face.fill(NULL_ITEM_LOCAL_ID);
769 rays_new_owner.fill(my_rank);
770 for( Integer i=0; i<nb_total_found; ++i ){
771 const FoundInfo& fi = global_founds_info[i];
772 Int32 owner = fi.owner;
776 Int32 local_id = fi.local_id;
778 Real distance = fi.distance;
779 if ((rays_face[ray]==NULL_ITEM_LOCAL_ID) || distance<distances[ray]){
780 distances[ray] = distance;
781 intersections[ray] =
Real3(fi.intersection.
x,fi.intersection.
y,fi.intersection.
z);
782 rays_face[ray] = fi.face_local_id;
783 rays_user_value[ray] = fi.user_value;
784 rays_new_owner[ray] = fi.contrib_owner;
803 Integer index = iitem.index();
804 orig_faces[index] = rays_orig_face[iitem];
805 user_values[index] = rays_user_value[iitem];
812 compute(local_positions,local_directions,orig_faces,user_values,out_intersections,out_distances,out_faces);
816 Integer index = iitem.index();
817 intersections[iitem] = out_intersections[index];
818 distances[iitem] = out_distances[index];
819 rays_face[iitem] = out_faces[index];
826 Integer nb_new_ray = ray_family->
nbItem();
828 local_directions.
resize(nb_new_ray);
829 local_positions.
resize(nb_new_ray);
831 Integer index = iitem.index();
832 local_distances[index] = distances[iitem];
833 local_directions[index] = rays_direction[iitem];
834 local_positions[index] = rays_position[iitem];
837 _writeSegments(my_rank,local_positions,local_directions,local_distances);
848void BasicRayMeshIntersection::
849_writeSegments(Int32 rank,
854#ifdef ARCANE_HAS_PACKAGE_LIMA
855 Lima::Maillage lima(
"segments");
856 lima.dimension(Lima::D3);
858 Integer nb_segment = positions.
size();
860 for( Integer i=0; i<nb_segment; ++i ){
861 Real t = distances[i];
864 lm_nodes[i*2].set_x(positions[i].x);
865 lm_nodes[i*2].set_y(positions[i].y);
866 lm_nodes[i*2].set_z(positions[i].z);
868 lm_nodes[(i*2)+1].set_x(positions[i].x + t*directions[i].x);
869 lm_nodes[(i*2)+1].set_y(positions[i].y + t*directions[i].y);
870 lm_nodes[(i*2)+1].set_z(positions[i].z + t*directions[i].z);
871 lima.ajouter(lm_nodes[(i*2)]);
872 lima.ajouter(lm_nodes[(i*2)+1]);
873 lima.ajouter(Lima::Bras(lm_nodes[i*2],lm_nodes[(i*2)+1]));
875 StringBuilder sb(
"segments");
878 std::string s(sb.toString().localstr());
882 ARCANE_UNUSED(positions);
883 ARCANE_UNUSED(directions);
884 ARCANE_UNUSED(distances);
885 ARCANE_THROW(NotSupportedException,
"Lima is not available");
893 BasicRayMeshIntersection);
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
bool computeIntersection(Real3 origin, Real3 direction, Int32 orig_face_local_id, Int32 face_local_id, Real3ConstArrayView face_nodes, Int32 *user_value, Real *distance, Real3 *position)
Calcul l'intersection entre un rayon et une face.
Service basique de calcul d'intersection entre segments et maillage.
virtual void build()
Construction de niveau build du service.
virtual void setFaceIntersector(IRayFaceIntersector *intersector)
Positionne le callback d'intersection.
virtual IRayFaceIntersector * faceIntersector()
Intersecteur utilisé (0 si aucun spécifié)
virtual void compute(Real3ConstArrayView segments_position, Real3ConstArrayView segments_direction, Int32ConstArrayView segments_orig_face, Int32ArrayView user_values, Real3ArrayView intersections, RealArrayView distances, Int32ArrayView faces_local_id)
Calcule l'intersection.
Classe de base de service lié à un sous-domaine.
Interface d'une famille d'entités.
virtual IParticleFamily * toParticleFamily()=0
Retourne l'interface de la famille de particule de cette famille.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual Int32 maxLocalId() const =0
virtual IMesh * mesh() const =0
Maillage associé
virtual Integer nbItem() const =0
Nombre d'entités.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable contenant le numéro du nouveau sous-domaine propriétaire de l'entité.
virtual FaceGroup outerFaces()=0
Groupe de toutes les faces sur la frontière.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
virtual void exchangeParticles()=0
Échange des entités.
Interface générique du calcul de l'intersection d'un rayon avec une face.
virtual bool computeIntersection(Real3 origin, Real3 direction, Int32 orig_face_local_id, Int32 face_local_id, Real3ConstArrayView face_nodes, Int32 *user_value, Real *distance, Real3 *intersection_position)=0
Calcul l'intersection entre un rayon et une face.
Calcul de l'intersection entre un ensemble de segments et la surface d'un maillage.
Integer size() const
Nombre d'éléments du groupe.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Int32 nbNode() const
Nombre de noeuds de l'entité
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
bool isOwn() const
true si l'entité est appartient au sous-domaine
Variable scalaire sur un type d'entité du maillage.
Vue sur les informations des particules.
Calcul l'intersection d'un rayon avec un ensemble de triangles en 3D.
void setRays(Real3ConstArrayView origins, Real3ConstArrayView directions)
Position la liste des rayons dont on souhaite calculer l'intersection.
Real checkIntersection(Real3 origin, Real3 direction, Real3 p0, Real3 p1, Real3 p2)
Calcul l'intersection de la demi-droite [origin,direction) avec le triangle (p0,p1,...
void compute()
Calcul l'intersection de chaque rayon avec la liste des triangles. Si un rayon intersecte plusieurs t...
void setTriangles(Real3ConstArrayView coordinates, Int32ConstArrayView indexes)
Positionne la liste des triangles dont on souhaite calculer l'intersection avec les rayons....
Int32ConstArrayView intersectedTriangleIndexes()
Indices des triangles intersectés. Indice dans le tableau donnée par setTriangles() du triangle inter...
RealConstArrayView distances()
Distance de l'origine d'un rayon à son point d'intersection. Distance (exprimée relativivement à la n...
Classe gérant un vecteur de réel de dimension 3.
Structure contenant les informations pour créer un service.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
void fill(const T &o) noexcept
Remplit le tableau avec la valeur o.
const T * data() const
Accès à la racine du tableau hors toute protection.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Exception lorsqu'une erreur fatale est survenue.
Interface du gestionnaire de traces.
Exception lorsqu'une fonction n'est pas implémentée.
Classe d'accès aux traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
Vecteur 1D de données avec sémantique par valeur (style STL).
ARCCORE_HOST_DEVICE Real3 vecMul(Real3 u, Real3 v)
Produit vectoriel de u par v. dans .
ARCCORE_HOST_DEVICE Real dot(Real2 u, Real2 v)
Produit scalaire de u par v dans .
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
ConstArrayView< Real3 > Real3ConstArrayView
Equivalent C d'un tableau à une dimension de Real3.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
unsigned char Byte
Type d'un octet.
Real y
deuxième composante du triplet
Real z
troisième composante du triplet
Real x
première composante du triplet