1 // Copyright (C) 2010-2012 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "vtkMedFamilyOnEntityOnProfile.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkMedUtilities.h"
24 #include "vtkMedFamilyOnEntity.h"
25 #include "vtkMedProfile.h"
26 #include "vtkMedEntityArray.h"
27 #include "vtkMedFamily.h"
28 #include "vtkMedField.h"
29 #include "vtkMedGrid.h"
30 #include "vtkMedMesh.h"
31 #include "vtkMedFieldOnProfile.h"
32 #include "vtkMedFieldOverEntity.h"
33 #include "vtkMedFieldStep.h"
34 #include "vtkMedFile.h"
35 #include "vtkMedGrid.h"
36 #include "vtkMedDriver.h"
37 #include "vtkMedUnstructuredGrid.h"
38 #include "vtkMedIntArray.h"
40 #include "vtkBitArray.h"
41 #include "vtkIdList.h"
43 #include "vtkMultiProcessController.h"
45 vtkCxxSetObjectMacro(vtkMedFamilyOnEntityOnProfile,FamilyOnEntity, vtkMedFamilyOnEntity);
46 vtkCxxSetObjectMacro(vtkMedFamilyOnEntityOnProfile, Profile, vtkMedProfile);
48 vtkCxxRevisionMacro(vtkMedFamilyOnEntityOnProfile, "$Revision$");
49 vtkStandardNewMacro(vtkMedFamilyOnEntityOnProfile)
51 vtkMedFamilyOnEntityOnProfile::vtkMedFamilyOnEntityOnProfile()
53 this->FamilyOnEntity = NULL;
55 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::NotComputed;
56 this->UseAllPoints = false;
57 this->MatchComputed = false;
61 vtkMedFamilyOnEntityOnProfile::~vtkMedFamilyOnEntityOnProfile()
63 this->SetFamilyOnEntity(NULL);
64 this->SetProfile(NULL);
67 bool vtkMedFamilyOnEntityOnProfile::KeepPoint(med_int index)
69 if(this->IntersectionStatus == NotComputed)
70 this->ComputeIntersection(NULL);
72 if(this->UseAllPoints)
75 if(this->MedToVTKPointIndexMap.find(index)
76 == this->MedToVTKPointIndexMap.end())
82 bool vtkMedFamilyOnEntityOnProfile::KeepCell(med_int index)
84 if(this->FamilyOnEntity->GetEntityArray()->GetFamilyId(index)
85 != this->FamilyOnEntity->GetFamily()->GetId())
90 int vtkMedFamilyOnEntityOnProfile::CanMapField(vtkMedFieldOnProfile* fop)
92 // only point fields can be mapped on point supports.
93 if(this->GetFamilyOnEntity()->GetEntity().EntityType == MED_NODE &&
94 fop->GetParentFieldOverEntity()->GetEntity().EntityType != MED_NODE)
97 // if it is a cell-centered field, the geometry need to be the same
98 if(fop->GetParentFieldOverEntity()->GetEntity().EntityType != MED_NODE
99 && fop->GetParentFieldOverEntity()->GetEntity().GeometryType !=
100 this->GetFamilyOnEntity()->GetEntity().GeometryType)
104 vtkMultiProcessController* controller =
105 vtkMultiProcessController::GetGlobalController();
106 if (controller != NULL)
108 numProc = controller->GetNumberOfProcesses();
111 if ((this->GetValid() == 0) && numProc == 1)
114 this->ComputeIntersection(fop);
116 if(this->IntersectionStatus == vtkMedFamilyOnEntityOnProfile::NoIntersection)
120 this->GetFamilyOnEntity()->GetEntity().EntityType != MED_NODE &&
121 fop->GetParentFieldOverEntity()->GetEntity().EntityType == MED_NODE &&
122 this->PointProfileMatch[fop->GetProfile()] == BadOrNoIntersection)
128 int vtkMedFamilyOnEntityOnProfile::CanShallowCopy(vtkMedFieldOnProfile *fop)
132 bool shallow_on_points = this->CanShallowCopyPointField(NULL);
133 bool shallow_on_cells = this->CanShallowCopyCellField(NULL);
134 if(shallow_on_points && shallow_on_cells)
136 if(!shallow_on_points && !shallow_on_cells)
138 vtkErrorMacro("CanShallowCopy cannot answer : is it a point or a cell field?");
142 if(fop->GetParentFieldOverEntity()->GetParentStep()->GetParentField()
143 ->GetFieldType() == vtkMedField::PointField)
144 return this->CanShallowCopyPointField(fop);
146 return this->CanShallowCopyCellField(fop);
149 void vtkMedFamilyOnEntityOnProfile::ComputeIntersection(vtkMedFieldOnProfile* fop)
151 int nodeOrCellSupport=this->GetFamilyOnEntity()->GetPointOrCell();
155 fieldType = fop->GetParentFieldOverEntity()->GetParentStep()->
156 GetParentField()->GetFieldType();
160 fieldType = (nodeOrCellSupport==vtkMedUtilities::OnPoint?vtkMedField::PointField:vtkMedField::CellField);
162 // Cell fields cannot match point supports
163 if(fieldType != vtkMedField::PointField
164 && nodeOrCellSupport == vtkMedUtilities::OnPoint)
166 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::NoIntersection;
167 this->UseAllPoints = false;
169 else if(fieldType != vtkMedField::PointField
170 && nodeOrCellSupport ==vtkMedUtilities::OnCell)
172 this->ComputeCellFamilyVsCellProfileMatch();
174 else if(fieldType == vtkMedField::PointField
175 && nodeOrCellSupport ==vtkMedUtilities::OnPoint)
177 vtkMedProfile* profile = NULL;
180 profile = fop->GetProfile();
182 // point fields must share the same profile as the point support.
183 this->ComputePointFamilyVsPointProfileMatch();
186 else if(fieldType == vtkMedField::PointField
187 && nodeOrCellSupport == vtkMedUtilities::OnCell)
189 vtkMedProfile* profile = NULL;
192 profile = fop->GetProfile();
194 this->ComputeCellFamilyVsPointProfileMatch(profile);
197 this->MatchComputed = true;
200 int vtkMedFamilyOnEntityOnProfile::CanShallowCopyPointField(vtkMedFieldOnProfile* fop)
202 vtkMedProfile* profile = (fop != NULL?fop->GetProfile(): NULL);
203 if(this->FamilyOnEntity->GetPointOrCell() == vtkMedUtilities::OnCell)
205 if(this->PointProfileMatch.find(profile) == this->PointProfileMatch.end())
207 this->ComputeCellFamilyVsPointProfileMatch(profile);
209 int match = this->PointProfileMatch[profile];
211 == vtkMedFamilyOnEntityOnProfile::ProfileEqualsSupport;
215 // this is a point support.
216 // The only case when there is shallow copy is if there is at most 1 family
217 // and the profile is shared.
218 if(this->Profile == profile &&
219 this->GetFamilyOnEntity()->GetEntityArray()
220 ->GetNumberOfFamilyOnEntity() <= 1)
231 int vtkMedFamilyOnEntityOnProfile::CanShallowCopyCellField(vtkMedFieldOnProfile* fop)
233 vtkMedProfile* profile = (fop != NULL?fop->GetProfile(): NULL);
234 // cell fields cannot be mapped to cell supports
235 if(this->FamilyOnEntity->GetPointOrCell() == vtkMedUtilities::OnPoint)
240 // this is a cell support.
241 if(this->Profile != profile)
246 // the only case I can shallow copy is if there is only one family
247 // defined on those cells.
248 if(this->Profile == NULL &&
249 this->GetFamilyOnEntity()->GetEntityArray()
250 ->GetNumberOfFamilyOnEntity() <= 1)
256 void vtkMedFamilyOnEntityOnProfile::ComputeUsedPoints()
258 this->MedToVTKPointIndexMap.clear();
260 //first test a few special cases where no heavy computing is necessary
261 vtkMedGrid* grid = this->FamilyOnEntity->GetParentGrid();
262 if(this->Profile == NULL)
264 // If there is no profile, the entity is on points and there
265 // at most 1 point family, then all points are used.
266 if(this->FamilyOnEntity->GetPointOrCell() == vtkMedUtilities::OnPoint &&
267 this->FamilyOnEntity->GetEntityArray()->GetNumberOfFamilyOnEntity() <= 1)
269 this->UseAllPoints = true;
272 // if there is no profile, the entity is on cell
273 // and there is at most 1 family on his entity, then all points are used
274 if(this->FamilyOnEntity->GetPointOrCell() == vtkMedUtilities::OnCell &&
275 this->FamilyOnEntity->GetEntityArray()->GetNumberOfFamilyOnEntity() <= 1)
277 this->UseAllPoints = true;
282 vtkSmartPointer<vtkBitArray> flag = vtkSmartPointer<vtkBitArray>::New();
283 flag->SetNumberOfTuples(grid->GetNumberOfPoints());
285 // initialize the array to false
286 for(vtkIdType pid = 0; pid < flag->GetNumberOfTuples(); pid++)
287 flag->SetValue(pid, false);
289 // for each cell, flag the used points
291 this->Profile->Load();
293 vtkMedIntArray* pids=(this->Profile!=NULL?this->Profile->GetIds():NULL);
295 med_int famId = this->FamilyOnEntity->GetFamily()->GetId();
296 vtkMedEntityArray* array = this->FamilyOnEntity->GetEntityArray();
297 vtkSmartPointer<vtkIdList> ids = vtkSmartPointer<vtkIdList>::New();
299 array->LoadConnectivity();
301 vtkIdType pflsize = (pids != NULL ? pids->GetNumberOfTuples():array->GetNumberOfEntity());
302 for(vtkIdType pindex=0; pindex<pflsize; pindex++)
304 med_int pid = (pids != NULL ? pids->GetValue(pindex)-1 : pindex);
305 med_int fid = array->GetFamilyId(pid);
308 // this cell is of the family and on the profile.
309 // --> flag all vertices of this cell
310 array->GetCellVertices(pid, ids);
311 for(int id = 0; id<ids->GetNumberOfIds(); id++)
313 vtkIdType subid = ids->GetId(id);
314 if(subid < 0 || subid >= flag->GetNumberOfTuples())
316 vtkDebugMacro("invalid sub id : " << subid);
320 flag->SetValue(subid, 1);
325 // now, the flag array contains all vertices used by this support
326 this->UseAllPoints = true;
327 for(vtkIdType pid = 0; pid<flag->GetNumberOfTuples(); pid++)
329 if(flag->GetValue(pid) == false)
331 this->UseAllPoints = false;
336 if(!this->UseAllPoints)
338 // If all points are not used, I compute the index mapping
339 vtkIdType vtk_index = 0;
341 for(vtkIdType pid=0; pid < flag->GetNumberOfTuples(); pid++)
343 if(flag->GetValue(pid) == true)
345 this->MedToVTKPointIndexMap[pid] = vtk_index;
352 void vtkMedFamilyOnEntityOnProfile::ComputeCellFamilyVsCellProfileMatch()
354 if(this->MatchComputed)
357 // this computes the UseAllPoints flag.
358 this->ComputeUsedPoints();
360 if(this->Profile == NULL)
362 // If there is no profile, then the match is exact if and only
363 // if there is 1 cell family on this entity
364 if(this->FamilyOnEntity->GetEntityArray()->GetNumberOfFamilyOnEntity() == 1)
366 this->IntersectionStatus =
367 vtkMedFamilyOnEntityOnProfile::ProfileIncludedInFamily;
371 this->IntersectionStatus =
372 vtkMedFamilyOnEntityOnProfile::ProfileIntersectsFamily;
377 this->Profile->Load();
378 vtkMedIntArray* pids=this->Profile->GetIds();
382 vtkErrorMacro("Could not load profile indices!");
383 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::NotComputed;
384 this->UseAllPoints = false;
388 med_int famId = this->GetFamilyOnEntity()->GetFamily()->GetId();
390 vtkMedEntityArray* array=this->FamilyOnEntity->GetEntityArray();
391 bool profile_included = true;
392 bool profile_intersect = false;
393 for(int pindex=0; pindex<pids->GetNumberOfTuples(); pindex++)
395 med_int pid=pids->GetValue(pindex)-1;
396 med_int fid=array->GetFamilyId(pid);
398 {// the current cell is on the familyand on the profile
399 // --> there is an overlap
400 profile_intersect = true;
404 // the cell is on the profile but not on the family --> no inclusion
405 profile_included=false;
409 if(profile_included && profile_intersect)
410 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::ProfileIncludedInFamily;
411 else if(profile_intersect)
412 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::ProfileIntersectsFamily;
414 this->IntersectionStatus = vtkMedFamilyOnEntityOnProfile::NoIntersection;
417 void vtkMedFamilyOnEntityOnProfile::
418 ComputeCellFamilyVsPointProfileMatch(vtkMedProfile* profile)
420 // first test if the cache is already set
421 if(this->PointProfileMatch.find(profile) != this->PointProfileMatch.end())
424 // this will compute the cell match cache, as well as the UseAllPoints flag.
425 this->ComputeCellFamilyVsCellProfileMatch();
429 // If there is no profile, then the match is at least partial.
430 // It is exact if and only
431 // if the cell family uses all points
432 int match = (this->UseAllPoints? ProfileEqualsSupport : ProfileLargerThanSupport);
433 this->PointProfileMatch[profile] =
434 (this->UseAllPoints? ProfileEqualsSupport : ProfileLargerThanSupport);
438 // if profile is not NULL and I use all points --> BadOrNoIntersection
439 if(this->UseAllPoints)
441 this->PointProfileMatch[profile] = BadOrNoIntersection;
446 vtkMedIntArray* pids=profile->GetIds();
450 vtkErrorMacro("profile indices could not be loaded!");
451 this->PointProfileMatch[profile] = BadOrNoIntersection;
456 bool exact_match = true;
457 vtkIdType numberOfUsedPoints = pids->GetNumberOfTuples();
458 for(med_int pindex=0; pindex < pids->GetNumberOfTuples(); pindex++)
460 med_int id = pids->GetValue(pindex);
461 if(this->MedToVTKPointIndexMap.find(id-1) == this->MedToVTKPointIndexMap.end())
463 // The given point profile index is not used by this support.
464 // the superposition is at most partial.
466 numberOfUsedPoints--;
470 // if this profile is smaller than the number of points, I can't match
471 // the profile to this support
472 if(numberOfUsedPoints < this->MedToVTKPointIndexMap.size())
474 this->PointProfileMatch[profile] = BadOrNoIntersection;
478 this->PointProfileMatch[profile] = ProfileEqualsSupport;
482 this->PointProfileMatch[profile] = ProfileLargerThanSupport;
486 void vtkMedFamilyOnEntityOnProfile::ComputePointFamilyVsPointProfileMatch()
488 if(this->MatchComputed)
491 this->ComputeUsedPoints();
493 if(this->Profile == NULL)
495 // If there is no profile, then the match is exact if there is at most
496 // 1 point family on the grid
497 if(this->FamilyOnEntity->GetParentGrid()->GetParentMesh()
498 ->GetNumberOfPointFamily() <= 1)
500 this->IntersectionStatus = ProfileIncludedInFamily;
504 // there is a profile, we have to compute the match between the family and
506 vtkMedFamilyOnEntity* foe = this->GetFamilyOnEntity();
507 vtkMedEntityArray* pea = foe->GetEntityArray();
508 vtkMedIntArray* pIds = NULL;
512 this->Profile->Load();
513 pIds=this->Profile->GetIds();
518 if(this->FamilyOnEntity->GetEntityArray()->GetNumberOfFamilyOnEntity() > 1)
520 this->IntersectionStatus =
521 vtkMedFamilyOnEntityOnProfile::ProfileIntersectsFamily;
525 this->IntersectionStatus =
526 vtkMedFamilyOnEntityOnProfile::ProfileIncludedInFamily;
531 bool profile_intersects=false;
532 bool profile_included=true;
533 med_int famId=this->FamilyOnEntity->GetFamily()->GetId();
534 for(vtkIdType pindex=0; pindex<pIds->GetNumberOfTuples(); pindex++)
536 med_int pid=pIds->GetValue(pindex)-1;
537 med_int fid = pea->GetFamilyId(pid);
538 // med_int fid=grid->GetPointFamilyId(pid);
540 {// the family of the current point is the good one
541 profile_intersects=true;
545 // we are on the profile and not on the family -->
546 // no exact match, but the the profile might be larger than the family.
547 profile_included=false;
551 if(!profile_intersects)
553 this->IntersectionStatus =
554 vtkMedFamilyOnEntityOnProfile::NoIntersection;
556 else if(profile_included)
558 this->IntersectionStatus =
559 vtkMedFamilyOnEntityOnProfile::ProfileIncludedInFamily;
563 this->IntersectionStatus =
564 vtkMedFamilyOnEntityOnProfile::ProfileIntersectsFamily;
568 vtkIdType vtkMedFamilyOnEntityOnProfile::GetVTKPointIndex(vtkIdType medCIndex)
570 if(this->IntersectionStatus == NotComputed)
571 this->ComputeIntersection(NULL);
573 if(this->UseAllPoints)
576 if(this->MedToVTKPointIndexMap.find(medCIndex)
577 == this->MedToVTKPointIndexMap.end())
579 vtkDebugMacro("GetVTKPointIndex asked for "
580 << medCIndex << " which has not been mapped");
584 return this->MedToVTKPointIndexMap[medCIndex];
587 void vtkMedFamilyOnEntityOnProfile::PrintSelf(ostream& os, vtkIndent indent)
589 this->Superclass::PrintSelf(os, indent);