1 // Copyright (C) 2007-2014 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, or (at your option) any later version.
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
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingPointSet.hxx"
22 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingUMesh.hxx"
25 #include "MEDCouplingMemArray.hxx"
26 #include "PlanarIntersector.txx"
27 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
28 #include "InterpKernelGeo2DNode.hxx"
29 #include "DirectedBoundingBox.hxx"
30 #include "InterpKernelAutoPtr.hxx"
36 using namespace ParaMEDMEM;
38 MEDCouplingPointSet::MEDCouplingPointSet():_coords(0)
42 MEDCouplingPointSet::MEDCouplingPointSet(const MEDCouplingPointSet& other, bool deepCopy):MEDCouplingMesh(other),_coords(0)
45 _coords=other._coords->performCpy(deepCopy);
48 MEDCouplingPointSet::~MEDCouplingPointSet()
54 int MEDCouplingPointSet::getNumberOfNodes() const
57 return _coords->getNumberOfTuples();
59 throw INTERP_KERNEL::Exception("Unable to get number of nodes because no coordinates specified !");
62 int MEDCouplingPointSet::getSpaceDimension() const
65 return _coords->getNumberOfComponents();
67 throw INTERP_KERNEL::Exception("Unable to get space dimension because no coordinates specified !");
70 void MEDCouplingPointSet::updateTime() const
74 updateTimeWith(*_coords);
78 std::size_t MEDCouplingPointSet::getHeapMemorySizeWithoutChildren() const
80 return MEDCouplingMesh::getHeapMemorySizeWithoutChildren();
83 std::vector<const BigMemoryObject *> MEDCouplingPointSet::getDirectChildren() const
85 std::vector<const BigMemoryObject *> ret;
87 ret.push_back(_coords);
91 void MEDCouplingPointSet::setCoords(const DataArrayDouble *coords)
93 if( coords != _coords )
97 _coords=const_cast<DataArrayDouble *>(coords);
105 * Returns a pointer to the array of point coordinates held by \a this.
106 * \return DataArrayDouble * - the pointer to the array of point coordinates. The
107 * caller is to delete this array using decrRef() as it is no more needed.
109 DataArrayDouble *MEDCouplingPointSet::getCoordinatesAndOwner() const
117 * Copies string attributes from an \a other mesh. The copied strings are
121 * - textual data of the coordinates array (name and components info)
123 * \param [in] other - the mesh to copy string attributes from.
125 void MEDCouplingPointSet::copyTinyStringsFrom(const MEDCouplingMesh *other)
127 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
129 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::copyTinyStringsFrom : meshes have not same type !");
130 MEDCouplingMesh::copyTinyStringsFrom(other);
131 if(_coords && otherC->_coords)
132 _coords->copyStringInfoFrom(*otherC->_coords);
135 bool MEDCouplingPointSet::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
138 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::isEqualIfNotWhy : null mesh instance in input !");
139 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
142 reason="mesh given in input is not castable in MEDCouplingPointSet !";
145 if(!MEDCouplingMesh::isEqualIfNotWhy(other,prec,reason))
147 if(!areCoordsEqualIfNotWhy(*otherC,prec,reason))
153 * Checks equality of point coordinates with coordinates of an \a other mesh.
154 * None textual data is considered.
155 * \param [in] other - the mesh to compare coordinates with \a this one.
156 * \param [in] prec - precision value to compare coordinates.
157 * \return bool - \a true if coordinates of points are equal, \a false else.
159 bool MEDCouplingPointSet::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
161 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
164 if(!areCoordsEqualWithoutConsideringStr(*otherC,prec))
169 bool MEDCouplingPointSet::areCoordsEqualIfNotWhy(const MEDCouplingPointSet& other, double prec, std::string& reason) const
171 if(_coords==0 && other._coords==0)
173 if(_coords==0 || other._coords==0)
175 reason="Only one PointSet between the two this and other has coordinate defined !";
178 if(_coords==other._coords)
180 bool ret=_coords->isEqualIfNotWhy(*other._coords,prec,reason);
182 reason.insert(0,"Coordinates DataArray do not match : ");
187 * Checks equality of point coordinates with \a other point coordinates.
188 * Textual data (name and components info) \b is compared as well.
189 * \param [in] other - the point coordinates to compare with \a this one.
190 * \param [in] prec - precision value to compare coordinates.
191 * \return bool - \a true if coordinates of points are equal, \a false else.
193 bool MEDCouplingPointSet::areCoordsEqual(const MEDCouplingPointSet& other, double prec) const
196 return areCoordsEqualIfNotWhy(other,prec,tmp);
200 * Checks equality of point coordinates with \a other point coordinates.
201 * None textual data is considered.
202 * \param [in] other - the point coordinates to compare with \a this one.
203 * \param [in] prec - precision value to compare coordinates.
204 * \return bool - \a true if coordinates of points are equal, \a false else.
206 bool MEDCouplingPointSet::areCoordsEqualWithoutConsideringStr(const MEDCouplingPointSet& other, double prec) const
208 if(_coords==0 && other._coords==0)
210 if(_coords==0 || other._coords==0)
212 if(_coords==other._coords)
214 return _coords->isEqualWithoutConsideringStr(*other._coords,prec);
218 * Returns coordinates of \a nodeId-th node.
219 * \param [in] nodeId - the ID of the node of interest.
220 * \param [in, out] coo - the array filled with coordinates of the \a nodeId-th
221 * node. This array is not cleared before filling in, the coordinates are
222 * appended to its end.
223 * \throw If the coordinates array is not set.
224 * \throw If \a nodeId is not a valid index for the coordinates array.
226 * \ref cpp_mcpointset_getcoordinatesofnode "Here is a C++ example".<br>
227 * \ref py_mcpointset_getcoordinatesofnode "Here is a Python example".
229 void MEDCouplingPointSet::getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const
232 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getCoordinatesOfNode : no coordinates array set !");
233 int nbNodes=getNumberOfNodes();
234 if(nodeId>=0 && nodeId<nbNodes)
236 const double *cooPtr=_coords->getConstPointer();
237 int spaceDim=getSpaceDimension();
238 coo.insert(coo.end(),cooPtr+spaceDim*nodeId,cooPtr+spaceDim*(nodeId+1));
242 std::ostringstream oss; oss << "MEDCouplingPointSet::getCoordinatesOfNode : request of nodeId \"" << nodeId << "\" but it should be in [0,"<< nbNodes << ") !";
243 throw INTERP_KERNEL::Exception(oss.str().c_str());
248 * Finds nodes equal within \a precision and returns an array describing the
249 * permutation to remove duplicated nodes.
250 * \param [in] precision - minimal absolute distance between two nodes at which they are
251 * considered not coincident.
252 * \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
253 * nodes have id strictly lower than \a limitTupleId then they are not
254 * returned. Put -1 to this parameter to have all nodes returned.
255 * \param [out] areNodesMerged - is set to \a true if any coincident nodes found.
256 * \param [out] newNbOfNodes - returns number of unique nodes.
257 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
258 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
259 * is to delete this array using decrRef() as it is no more needed.
260 * \throw If the coordinates array is not set.
262 DataArrayInt *MEDCouplingPointSet::buildPermArrayForMergeNode(double precision, int limitNodeId, bool& areNodesMerged, int& newNbOfNodes) const
264 DataArrayInt *comm,*commI;
265 findCommonNodes(precision,limitNodeId,comm,commI);
266 int oldNbOfNodes=getNumberOfNodes();
267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildNewNumberingFromCommonNodesFormat(comm,commI,newNbOfNodes);
268 areNodesMerged=(oldNbOfNodes!=newNbOfNodes);
275 * Finds nodes coincident within \a prec tolerance.
276 * Ids of coincident nodes are stored in output arrays.
277 * A pair of arrays (\a comm, \a commIndex) is called "Surjective Format 2".
278 * \param [in] prec - minimal absolute distance (using infinite norm) between two nodes at which they are
279 * considered not coincident.
280 * \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
281 * nodes have id strictly lower than \a limitTupleId then they are not
282 * returned. Put -1 to this parameter to have all nodes treated.
283 * \param [out] comm - the array holding ids of coincident nodes.
284 * \a comm->getNumberOfComponents() == 1.
285 * \a comm->getNumberOfTuples() == \a commIndex->back(). The caller
286 * is to delete this array using decrRef() as it is no more needed.
287 * \param [out] commIndex - the array dividing all ids stored in \a comm into
288 * groups of (ids of) coincident nodes. Its every value is a tuple
289 * index where a next group of nodes begins. For example the second
290 * group of nodes in \a comm is described by following range of indices:
291 * [ \a commIndex[1], \a commIndex[2] ). \a commIndex->getNumberOfTuples()-1
292 * gives the number of groups of coincident nodes. The caller
293 * is to delete this array using decrRef() as it is no more needed.
294 * \throw If the coordinates array is not set.
296 * \ref cpp_mcpointset_findcommonnodes "Here is a C++ example".<br>
297 * \ref py_mcpointset_findcommonnodes "Here is a Python example".
299 void MEDCouplingPointSet::findCommonNodes(double prec, int limitNodeId, DataArrayInt *&comm, DataArrayInt *&commIndex) const
302 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findCommonNodes : no coords specified !");
303 _coords->findCommonTuples(prec,limitNodeId,comm,commIndex);
307 * Finds nodes located at distances lower that \a eps from a given point.
308 * \param [in] pos - pointer to coordinates of the point. This array is expected to
309 * be of length \a this->getSpaceDimension() at least, else the
310 * behavior is not warranted.
311 * \param [in] eps - the lowest distance between a point and a node (using infinite norm) at which the node is
312 * not returned by this method.
313 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of nodes
314 * close to the point. The caller is to delete this
315 * array using decrRef() as it is no more needed.
316 * \throw If the coordinates array is not set.
318 * \ref cpp_mcpointset_getnodeidsnearpoint "Here is a C++ example".<br>
319 * \ref py_mcpointset_getnodeidsnearpoint "Here is a Python example".
321 DataArrayInt *MEDCouplingPointSet::getNodeIdsNearPoint(const double *pos, double eps) const
323 DataArrayInt *c=0,*cI=0;
324 getNodeIdsNearPoints(pos,1,eps,c,cI);
325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cITmp(cI);
330 * Finds nodes located at distances lower that \a eps from given points.
331 * \param [in] pos - pointer to coordinates of the points. This array is expected to
332 * be of length \a nbOfPoints * \a this->getSpaceDimension() at least, else the
333 * behavior is not warranted.
334 * \param [in] nbOfPoints - number of points whose coordinates are given by \a pos
336 * \param [in] eps - the lowest distance between (using infinite norm) a point and a node at which the node is
337 * not returned by this method.
338 * \param [out] c - array returning ids of nodes located closer than \a eps to the
339 * given points. The caller
340 * is to delete this array using decrRef() as it is no more needed.
341 * \param [out] cI - for each i-th given point, the array specifies tuples of \a c
342 * holding ids of nodes close to the i-th point. <br>The i-th value of \a cI is an
343 * index of tuple of \a c holding id of a first (if any) node close to the
344 * i-th given point. Difference between the i-th and (i+1)-th value of \a cI
345 * (i.e. \a cI[ i+1 ] - \a cI[ i ]) defines number of nodes close to the i-th
346 * point (that can be zero!). For example, the group of nodes close to the
347 * second point is described by following range of indices [ \a cI[1], \a cI[2] ).
348 * The caller is to delete this array using decrRef() as it is no more needed.
349 * \throw If the coordinates array is not set.
351 * \ref cpp_mcpointset_getnodeidsnearpoints "Here is a C++ example".<br>
352 * \ref py_mcpointset_getnodeidsnearpoints "Here is a Python example".
354 void MEDCouplingPointSet::getNodeIdsNearPoints(const double *pos, int nbOfPoints, double eps, DataArrayInt *& c, DataArrayInt *& cI) const
357 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getNodeIdsNearPoint : no coordiantes set !");
358 int spaceDim=getSpaceDimension();
359 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> points=DataArrayDouble::New();
360 points->useArray(pos,false,CPP_DEALLOC,nbOfPoints,spaceDim);
361 _coords->computeTupleIdsNearTuples(points,eps,c,cI);
365 * @param comm in param in the same format than one returned by findCommonNodes method.
366 * @param commI in param in the same format than one returned by findCommonNodes method.
367 * @return the old to new correspondance array.
369 DataArrayInt *MEDCouplingPointSet::buildNewNumberingFromCommonNodesFormat(const DataArrayInt *comm, const DataArrayInt *commIndex,
370 int& newNbOfNodes) const
373 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::buildNewNumberingFromCommonNodesFormat : no coords specified !");
374 return DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfNodes(),comm->begin(),commIndex->begin(),commIndex->end(),newNbOfNodes);
378 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
379 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
380 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
381 * array is modified accordingly.
382 * \param [in] newNodeNumbers - a permutation array, of length \a
383 * this->getNumberOfNodes(), in "Old to New" mode.
384 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
385 * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
386 * \throw If the coordinates array is not set.
387 * \throw If the nodal connectivity of cells is not defined.
389 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
390 * \ref py_mcumesh_renumberNodes "Here is a Python example".
392 void MEDCouplingPointSet::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
395 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::renumberNodes : no coords specified !");
396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=_coords->renumberAndReduce(newNodeNumbers,newNbOfNodes);
397 renumberNodesInConn(newNodeNumbers);
398 setCoords(newCoords);//let it here not before renumberNodesInConn because old number of nodes is sometimes used...
402 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
403 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
404 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
405 * array is modified accordingly. In contrast to renumberNodes(), location
406 * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
407 * \param [in] newNodeNumbers - a permutation array, of length \a
408 * this->getNumberOfNodes(), in "Old to New" mode.
409 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
410 * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
411 * actually one more than the maximal id in \a newNodeNumbers.
412 * \throw If the coordinates array is not set.
413 * \throw If the nodal connectivity of cells is not defined.
415 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
416 * \ref py_mcumesh_renumberNodes "Here is a Python example".
418 void MEDCouplingPointSet::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
420 DataArrayDouble *newCoords=DataArrayDouble::New();
421 std::vector<int> div(newNbOfNodes);
422 int spaceDim=getSpaceDimension();
423 newCoords->alloc(newNbOfNodes,spaceDim);
424 newCoords->copyStringInfoFrom(*_coords);
425 newCoords->fillWithZero();
426 int oldNbOfNodes=getNumberOfNodes();
427 double *ptToFill=newCoords->getPointer();
428 const double *oldCoordsPtr=_coords->getConstPointer();
429 for(int i=0;i<oldNbOfNodes;i++)
431 std::transform(oldCoordsPtr+i*spaceDim,oldCoordsPtr+(i+1)*spaceDim,ptToFill+newNodeNumbers[i]*spaceDim,
432 ptToFill+newNodeNumbers[i]*spaceDim,std::plus<double>());
433 div[newNodeNumbers[i]]++;
435 for(int i=0;i<newNbOfNodes;i++)
436 ptToFill=std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)div[i]));
437 setCoords(newCoords);
438 newCoords->decrRef();
439 renumberNodesInConn(newNodeNumbers);
443 * Computes the minimum box bounding all nodes. The edges of the box are parallel to
444 * the Cartesian coordinate axes. The bounding box is described by coordinates of its
445 * two extremum points with minimal and maximal coordinates.
446 * \param [out] bbox - array filled with coordinates of extremum points in "no
447 * interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin, zMax (if in 3D). This
448 * array, of length 2 * \a this->getSpaceDimension() at least, is to be
449 * pre-allocated by the caller.
450 * \throw If the coordinates array is not set.
452 * \ref cpp_mcpointset_getBoundingBox "Here is a C++ example".<br>
453 * \ref py_mcpointset_getBoundingBox "Here is a Python example".
455 void MEDCouplingPointSet::getBoundingBox(double *bbox) const
458 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getBoundingBox : Coordinates not set !");
459 _coords->getMinMaxPerComponent(bbox);
463 * Removes "free" nodes, i.e. nodes not used to define any element.
464 * \throw If the coordinates array is not set.
465 * \throw If the elements are not defined.
467 void MEDCouplingPointSet::zipCoords()
470 DataArrayInt *traducer=zipCoordsTraducer();
474 struct MEDCouplingCompAbs
476 bool operator()(double x, double y) { return std::abs(x)<std::abs(y);}
480 * Returns the carateristic dimension of \a this point set, that is a maximal
481 * absolute values of node coordinates.
482 * \throw If the coordinates array is not set.
484 double MEDCouplingPointSet::getCaracteristicDimension() const
487 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getCaracteristicDimension : Coordinates not set !");
488 const double *coords=_coords->getConstPointer();
489 int nbOfValues=_coords->getNbOfElems();
490 return std::abs(*std::max_element(coords,coords+nbOfValues,MEDCouplingCompAbs()));
494 * This method recenter coordinates of nodes in \b this in order to be centered at the origin to benefit about the advantages of the precision to be around the box
495 * around origin of 'radius' 1.
497 * \warning this method is non const and alterates coordinates in \b this without modifying.
498 * \param [in] eps absolute epsilon. under that value of delta between max and min no scale is performed.
501 void MEDCouplingPointSet::recenterForMaxPrecision(double eps)
504 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::recenterForMaxPrecision : Coordinates not set !");
505 _coords->recenterForMaxPrecision(eps);
510 * Rotates \a this set of nodes by \a angle around either an axis (in 3D) or a point
512 * \param [in] center - coordinates either of an origin of rotation axis (in 3D) or
513 * of center of rotation (in 2D). This array is to be of size \a
514 * this->getSpaceDimension() at least.
515 * \param [in] vector - 3 components of a vector defining direction of the rotation
516 * axis in 3D. In 2D this parameter is not used.
517 * \param [in] angle - the rotation angle in radians.
518 * \throw If the coordinates array is not set.
519 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
520 * \throw If \a center == NULL
521 * \throw If \a vector == NULL && \a this->getSpaceDimension() == 3.
522 * \throw If Magnitude of \a vector is zero.
524 * \ref cpp_mcpointset_rotate "Here is a C++ example".<br>
525 * \ref py_mcpointset_rotate "Here is a Python example".
527 void MEDCouplingPointSet::rotate(const double *center, const double *vector, double angle)
529 int spaceDim=getSpaceDimension();
531 rotate3D(center,vector,angle);
533 rotate2D(center,angle);
535 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::rotate : invalid space dim for rotation must be 2 or 3");
536 _coords->declareAsNew();
541 * Translates \a this set of nodes.
542 * \param [in] vector - components of a translation vector. This array is to be of
543 * size \a this->getSpaceDimension() at least.
544 * \throw If the coordinates array is not set.
545 * \throw If \a vector == NULL.
547 * \ref cpp_mcpointset_translate "Here is a C++ example".<br>
548 * \ref py_mcpointset_translate "Here is a Python example".
550 void MEDCouplingPointSet::translate(const double *vector)
553 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::translate : NULL input vector !");
555 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::translate : no coordinates set !");
556 double *coords=_coords->getPointer();
557 int nbNodes=getNumberOfNodes();
558 int dim=getSpaceDimension();
559 for(int i=0; i<nbNodes; i++)
560 for(int idim=0; idim<dim;idim++)
561 coords[i*dim+idim]+=vector[idim];
562 _coords->declareAsNew();
568 * Applies scaling transformation to \a this set of nodes.
569 * \param [in] point - coordinates of a scaling center. This array is to be of
570 * size \a this->getSpaceDimension() at least.
571 * \param [in] factor - a scale factor.
572 * \throw If the coordinates array is not set.
573 * \throw If \a point == NULL.
575 * \ref cpp_mcpointset_scale "Here is a C++ example".<br>
576 * \ref py_mcpointset_scale "Here is a Python example".
578 void MEDCouplingPointSet::scale(const double *point, double factor)
581 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::scale : NULL input point !");
583 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::scale : no coordinates set !");
584 double *coords=_coords->getPointer();
585 int nbNodes=getNumberOfNodes();
586 int dim=getSpaceDimension();
587 for(int i=0;i<nbNodes;i++)
589 std::transform(coords+i*dim,coords+(i+1)*dim,point,coords+i*dim,std::minus<double>());
590 std::transform(coords+i*dim,coords+(i+1)*dim,coords+i*dim,std::bind2nd(std::multiplies<double>(),factor));
591 std::transform(coords+i*dim,coords+(i+1)*dim,point,coords+i*dim,std::plus<double>());
593 _coords->declareAsNew();
598 * Converts \a this set of points to an other dimension by changing number of
599 * components of point coordinates. If the dimension increases, added components
600 * are filled with \a dftValue. If the dimension decreases, last components are lost.
601 * If the new dimension is same as \a this->getSpaceDimension(), nothing is done.
602 * \param [in] newSpaceDim - the new space dimension.
603 * \param [in] dftValue - the value to assign to added components of point coordinates
604 * (if the dimension increases).
605 * \throw If the coordinates array is not set.
606 * \throw If \a newSpaceDim < 1.
608 void MEDCouplingPointSet::changeSpaceDimension(int newSpaceDim, double dftValue)
611 throw INTERP_KERNEL::Exception("changeSpaceDimension must be called on an MEDCouplingPointSet instance with coordinates set !");
613 throw INTERP_KERNEL::Exception("changeSpaceDimension must be called a newSpaceDim >=1 !");
614 int oldSpaceDim=getSpaceDimension();
615 if(newSpaceDim==oldSpaceDim)
617 DataArrayDouble *newCoords=getCoords()->changeNbOfComponents(newSpaceDim,dftValue);
618 setCoords(newCoords);
619 newCoords->decrRef();
624 * Substitutes \a this->_coords with \a other._coords provided that coordinates of
625 * the two point sets match with a specified precision, else an exception is thrown.
626 * \param [in] other - the other point set whose coordinates array will be used by
627 * \a this point set in case of their equality.
628 * \param [in] epsilon - the precision used to compare coordinates.
629 * \throw If the coordinates array of \a this is not set.
630 * \throw If the coordinates array of \a other is not set.
631 * \throw If the coordinates of \a this and \a other do not match.
633 void MEDCouplingPointSet::tryToShareSameCoords(const MEDCouplingPointSet& other, double epsilon)
635 if(_coords==other._coords)
638 throw INTERP_KERNEL::Exception("Current instance has no coords whereas other has !");
640 throw INTERP_KERNEL::Exception("Other instance has no coords whereas current has !");
641 if(!_coords->isEqualWithoutConsideringStr(*other._coords,epsilon))
642 throw INTERP_KERNEL::Exception("Coords are not the same !");
643 setCoords(other._coords);
647 * This method duplicates the nodes whose ids are in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) and put the result of their duplication at the end
648 * of existing node ids.
650 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
651 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
653 void MEDCouplingPointSet::duplicateNodesInCoords(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
656 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::duplicateNodesInCoords : no coords set !");
657 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=_coords->selectByTupleIdSafe(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
658 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords2=DataArrayDouble::Aggregate(_coords,newCoords);
659 setCoords(newCoords2);
663 * Finds nodes located at distance lower that \a eps from a specified plane.
664 * \param [in] pt - 3 components of a point defining location of the plane.
665 * \param [in] vec - 3 components of a normal vector to the plane. Vector magnitude
666 * must be greater than 10*\a eps.
667 * \param [in] eps - maximal distance of a node from the plane at which the node is
668 * considered to lie on the plane.
669 * \param [in,out] nodes - a vector returning ids of found nodes. This vector is not
670 * cleared before filling in.
671 * \throw If the coordinates array is not set.
672 * \throw If \a pt == NULL.
673 * \throw If \a vec == NULL.
674 * \throw If the magnitude of \a vec is zero.
675 * \throw If \a this->getSpaceDimension() != 3.
677 void MEDCouplingPointSet::findNodesOnPlane(const double *pt, const double *vec, double eps, std::vector<int>& nodes) const
679 if(getSpaceDimension()!=3)
680 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : Invalid spacedim to be applied on this ! Must be equal to 3 !");
682 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : NULL point pointer specified !");
684 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : NULL vector pointer specified !");
685 int nbOfNodes=getNumberOfNodes();
686 double a=vec[0],b=vec[1],c=vec[2],d=-pt[0]*vec[0]-pt[1]*vec[1]-pt[2]*vec[2];
687 double deno=sqrt(a*a+b*b+c*c);
688 if(deno<std::numeric_limits<double>::min())
689 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : vector pointer specified has norm equal to 0. !");
690 const double *work=_coords->getConstPointer();
691 for(int i=0;i<nbOfNodes;i++)
693 if(std::abs(a*work[0]+b*work[1]+c*work[2]+d)/deno<eps)
700 * Finds nodes located at distance lower that \a eps from a specified line in 2D and 3D.
701 * \param [in] pt - components of coordinates of an initial point of the line. This
702 * array is to be of size \a this->getSpaceDimension() at least.
703 * \param [in] vec - components of a vector defining the line direction. This array
704 * is to be of size \a this->getSpaceDimension() at least. Vector magnitude
705 * must be greater than 10*\a eps.
706 * \param [in] eps - maximal distance of a node from the line at which the node is
707 * considered to lie on the line.
708 * \param [in,out] nodes - a vector returning ids of found nodes. This vector is not
709 * cleared before filling in.
710 * \throw If the coordinates array is not set.
711 * \throw If \a pt == NULL.
712 * \throw If \a vec == NULL.
713 * \throw If the magnitude of \a vec is zero.
714 * \throw If ( \a this->getSpaceDimension() != 3 && \a this->getSpaceDimension() != 2 ).
716 void MEDCouplingPointSet::findNodesOnLine(const double *pt, const double *vec, double eps, std::vector<int>& nodes) const
718 int spaceDim=getSpaceDimension();
719 if(spaceDim!=2 && spaceDim!=3)
720 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : Invalid spacedim to be applied on this ! Must be equal to 2 or 3 !");
722 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : NULL point pointer specified !");
724 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : NULL vector pointer specified !");
725 int nbOfNodes=getNumberOfNodes();
727 for(int i=0;i<spaceDim;i++)
729 double deno=sqrt(den);
731 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : Invalid given direction vector ! Norm is too small !");
732 INTERP_KERNEL::AutoPtr<double> vecn=new double[spaceDim];
733 for(int i=0;i<spaceDim;i++)
735 const double *work=_coords->getConstPointer();
738 for(int i=0;i<nbOfNodes;i++)
740 if(std::abs(vecn[0]*(work[1]-pt[1])-vecn[1]*(work[0]-pt[0]))<eps)
747 for(int i=0;i<nbOfNodes;i++)
749 double a=vecn[0]*(work[1]-pt[1])-vecn[1]*(work[0]-pt[0]);
750 double b=vecn[1]*(work[2]-pt[2])-vecn[2]*(work[1]-pt[1]);
751 double c=vecn[2]*(work[0]-pt[0])-vecn[0]*(work[2]-pt[2]);
752 if(std::sqrt(a*a+b*b+c*c)<eps)
760 * Returns a new array of node coordinates by concatenating node coordinates of two
761 * given point sets, so that (1) the number of nodes in the result array is a sum of the
762 * number of nodes of given point sets and (2) the number of component in the result array
763 * is same as that of each of given point sets. Info on components is copied from the first
764 * of the given point set. Space dimension of the given point sets must be the same.
765 * \param [in] m1 - a point set whose coordinates will be included in the result array.
766 * \param [in] m2 - another point set whose coordinates will be included in the
768 * \return DataArrayDouble * - the new instance of DataArrayDouble.
769 * The caller is to delete this result array using decrRef() as it is no more
771 * \throw If both \a m1 and \a m2 are NULL.
772 * \throw If \a m1->getSpaceDimension() != \a m2->getSpaceDimension().
774 DataArrayDouble *MEDCouplingPointSet::MergeNodesArray(const MEDCouplingPointSet *m1, const MEDCouplingPointSet *m2)
776 int spaceDim=m1->getSpaceDimension();
777 if(spaceDim!=m2->getSpaceDimension())
778 throw INTERP_KERNEL::Exception("Mismatch in SpaceDim during call of MergeNodesArray !");
779 return DataArrayDouble::Aggregate(m1->getCoords(),m2->getCoords());
782 DataArrayDouble *MEDCouplingPointSet::MergeNodesArray(const std::vector<const MEDCouplingPointSet *>& ms)
785 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : input array must be NON EMPTY !");
786 std::vector<const MEDCouplingPointSet *>::const_iterator it=ms.begin();
787 std::vector<const DataArrayDouble *> coo(ms.size());
788 int spaceDim=(*it)->getSpaceDimension();
789 coo[0]=(*it++)->getCoords();
790 if(!coo[0]->isAllocated())
791 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : first element in coordinates is not allocated !");
792 for(int i=1;it!=ms.end();it++,i++)
794 const DataArrayDouble *tmp=(*it)->getCoords();
797 if(tmp->isAllocated())
799 if((*it)->getSpaceDimension()==spaceDim)
802 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Mismatch in SpaceDim !");
805 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Presence of a non allocated array !");
808 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Empty coords detected !");
810 return DataArrayDouble::Aggregate(coo);
814 * Factory to build new instance of instanciable subclasses of MEDCouplingPointSet.
815 * This method is used during unserialization process.
817 MEDCouplingPointSet *MEDCouplingPointSet::BuildInstanceFromMeshType(MEDCouplingMeshType type)
822 return MEDCouplingUMesh::New();
823 case SINGLE_STATIC_GEO_TYPE_UNSTRUCTURED:
824 return MEDCoupling1SGTUMesh::New();
825 case SINGLE_DYNAMIC_GEO_TYPE_UNSTRUCTURED:
826 return MEDCoupling1DGTUMesh::New();
828 throw INTERP_KERNEL::Exception("Invalid type of mesh specified");
833 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
835 void MEDCouplingPointSet::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
838 double time=getTime(it,order);
841 int spaceDim=getSpaceDimension();
842 littleStrings.resize(spaceDim+4);
843 littleStrings[0]=getName();
844 littleStrings[1]=getDescription();
845 littleStrings[2]=_coords->getName();
846 littleStrings[3]=getTimeUnit();
847 for(int i=0;i<spaceDim;i++)
848 littleStrings[i+4]=getCoords()->getInfoOnComponent(i);
850 tinyInfo.push_back(getType());
851 tinyInfo.push_back(spaceDim);
852 tinyInfo.push_back(getNumberOfNodes());
853 tinyInfo.push_back(it);
854 tinyInfo.push_back(order);
855 tinyInfoD.push_back(time);
859 littleStrings.resize(3);
860 littleStrings[0]=getName();
861 littleStrings[1]=getDescription();
862 littleStrings[2]=getTimeUnit();
864 tinyInfo.push_back(getType());
865 tinyInfo.push_back(-1);
866 tinyInfo.push_back(-1);
867 tinyInfo.push_back(it);
868 tinyInfo.push_back(order);
869 tinyInfoD.push_back(time);
874 * Third and final step of serialization process.
876 void MEDCouplingPointSet::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
880 a2=const_cast<DataArrayDouble *>(getCoords());
888 * Second step of serialization process.
889 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
891 void MEDCouplingPointSet::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
893 if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
895 a2->alloc(tinyInfo[2],tinyInfo[1]);
896 littleStrings.resize(tinyInfo[1]+4);
900 littleStrings.resize(3);
905 * Second and final unserialization process.
906 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
908 void MEDCouplingPointSet::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
910 if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
913 setName(littleStrings[0]);
914 setDescription(littleStrings[1]);
915 a2->setName(littleStrings[2]);
916 setTimeUnit(littleStrings[3]);
917 for(int i=0;i<tinyInfo[1];i++)
918 getCoords()->setInfoOnComponent(i,littleStrings[i+4]);
919 setTime(tinyInfoD[0],tinyInfo[3],tinyInfo[4]);
923 setName(littleStrings[0]);
924 setDescription(littleStrings[1]);
925 setTimeUnit(littleStrings[2]);
926 setTime(tinyInfoD[0],tinyInfo[3],tinyInfo[4]);
930 void MEDCouplingPointSet::checkCoherency() const
933 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkCoherency : no coordinates set !");
937 * Intersect Bounding Box given 2 Bounding Boxes.
939 bool MEDCouplingPointSet::intersectsBoundingBox(const double* bb1, const double* bb2, int dim, double eps)
941 double* bbtemp = new double[2*dim];
944 for (int i=0; i< dim; i++)
946 double delta = bb1[2*i+1]-bb1[2*i];
947 if ( delta > deltamax )
952 for (int i=0; i<dim; i++)
954 bbtemp[i*2]=bb1[i*2]-deltamax*eps;
955 bbtemp[i*2+1]=bb1[i*2+1]+deltamax*eps;
958 for (int idim=0; idim < dim; idim++)
960 bool intersects = (bbtemp[idim*2]<bb2[idim*2+1])
961 && (bb2[idim*2]<bbtemp[idim*2+1]) ;
973 * Intersect 2 given Bounding Boxes.
975 bool MEDCouplingPointSet::intersectsBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bb1, const double* bb2, int dim, double eps)
977 double* bbtemp = new double[2*dim];
980 for (int i=0; i< dim; i++)
982 double delta = bb2[2*i+1]-bb2[2*i];
983 if ( delta > deltamax )
988 for (int i=0; i<dim; i++)
990 bbtemp[i*2]=bb2[i*2]-deltamax*eps;
991 bbtemp[i*2+1]=bb2[i*2+1]+deltamax*eps;
994 bool intersects = !bb1.isDisjointWith( bbtemp );
1000 * 'This' is expected to be of spaceDim==3. Idem for 'center' and 'vect'
1002 void MEDCouplingPointSet::rotate3D(const double *center, const double *vect, double angle)
1004 double *coords=_coords->getPointer();
1005 int nbNodes=getNumberOfNodes();
1006 Rotate3DAlg(center,vect,angle,nbNodes,coords);
1010 * Low static method that operates 3D rotation of 'nbNodes' 3D nodes whose coordinates are arranged in 'coords'
1011 * around an axe ('center','vect') and with angle 'angle'.
1013 void MEDCouplingPointSet::Rotate3DAlg(const double *center, const double *vect, double angle, int nbNodes, double *coords)
1015 if(!center || !vect)
1016 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::Rotate3DAlg : null vector in input !");
1017 double sina=sin(angle);
1018 double cosa=cos(angle);
1019 double vectorNorm[3];
1021 double matrixTmp[9];
1022 double norm=sqrt(vect[0]*vect[0]+vect[1]*vect[1]+vect[2]*vect[2]);
1023 if(norm<std::numeric_limits<double>::min())
1024 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::Rotate3DAlg : magnitude of input vector is too close of 0. !");
1025 std::transform(vect,vect+3,vectorNorm,std::bind2nd(std::multiplies<double>(),1/norm));
1026 //rotation matrix computation
1027 matrix[0]=cosa; matrix[1]=0.; matrix[2]=0.; matrix[3]=0.; matrix[4]=cosa; matrix[5]=0.; matrix[6]=0.; matrix[7]=0.; matrix[8]=cosa;
1028 matrixTmp[0]=vectorNorm[0]*vectorNorm[0]; matrixTmp[1]=vectorNorm[0]*vectorNorm[1]; matrixTmp[2]=vectorNorm[0]*vectorNorm[2];
1029 matrixTmp[3]=vectorNorm[1]*vectorNorm[0]; matrixTmp[4]=vectorNorm[1]*vectorNorm[1]; matrixTmp[5]=vectorNorm[1]*vectorNorm[2];
1030 matrixTmp[6]=vectorNorm[2]*vectorNorm[0]; matrixTmp[7]=vectorNorm[2]*vectorNorm[1]; matrixTmp[8]=vectorNorm[2]*vectorNorm[2];
1031 std::transform(matrixTmp,matrixTmp+9,matrixTmp,std::bind2nd(std::multiplies<double>(),1-cosa));
1032 std::transform(matrix,matrix+9,matrixTmp,matrix,std::plus<double>());
1033 matrixTmp[0]=0.; matrixTmp[1]=-vectorNorm[2]; matrixTmp[2]=vectorNorm[1];
1034 matrixTmp[3]=vectorNorm[2]; matrixTmp[4]=0.; matrixTmp[5]=-vectorNorm[0];
1035 matrixTmp[6]=-vectorNorm[1]; matrixTmp[7]=vectorNorm[0]; matrixTmp[8]=0.;
1036 std::transform(matrixTmp,matrixTmp+9,matrixTmp,std::bind2nd(std::multiplies<double>(),sina));
1037 std::transform(matrix,matrix+9,matrixTmp,matrix,std::plus<double>());
1038 //rotation matrix computed.
1040 for(int i=0; i<nbNodes; i++)
1042 std::transform(coords+i*3,coords+(i+1)*3,center,tmp,std::minus<double>());
1043 coords[i*3]=matrix[0]*tmp[0]+matrix[1]*tmp[1]+matrix[2]*tmp[2]+center[0];
1044 coords[i*3+1]=matrix[3]*tmp[0]+matrix[4]*tmp[1]+matrix[5]*tmp[2]+center[1];
1045 coords[i*3+2]=matrix[6]*tmp[0]+matrix[7]*tmp[1]+matrix[8]*tmp[2]+center[2];
1050 * This method allows to give for each cell in \a trgMesh, how much it interacts with cells of \a srcMesh.
1051 * The returned array can be seen as a weighted array on the target cells of \a trgMesh input parameter.
1053 * \param [in] srcMesh - source mesh
1054 * \param [in] trgMesh - target mesh
1055 * \param [in] eps - precision of the detection
1056 * \return DataArrayInt * - An array that gives for each cell of \a trgMesh, how many cells in \a srcMesh (regarding the precision of detection \a eps) can interacts.
1058 * \throw If \a srcMesh and \a trgMesh have not the same space dimension.
1060 DataArrayInt *MEDCouplingPointSet::ComputeNbOfInteractionsWithSrcCells(const MEDCouplingPointSet *srcMesh, const MEDCouplingPointSet *trgMesh, double eps)
1062 if(!srcMesh || !trgMesh)
1063 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::ComputeNbOfInteractionsWithSrcCells : the input meshes must be not NULL !");
1064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> sbbox(srcMesh->getBoundingBoxForBBTree()),tbbox(trgMesh->getBoundingBoxForBBTree());
1065 return tbbox->computeNbOfInteractionsWith(sbbox,eps);
1069 * Creates a new MEDCouplingMesh containing a part of cells of \a this mesh. The new
1070 * mesh shares a coordinates array with \a this one. The cells to include to the
1071 * result mesh are specified by an array of cell ids.
1072 * \param [in] start - an array of cell ids to include to the result mesh.
1073 * \param [in] end - specifies the end of the array \a start, so that
1074 * the last value of \a start is \a end[ -1 ].
1075 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
1076 * delete this mesh using decrRef() as it is no more needed.
1078 MEDCouplingMesh *MEDCouplingPointSet::buildPart(const int *start, const int *end) const
1080 return buildPartOfMySelf(start,end,true);
1084 * Creates a new MEDCouplingMesh containing a part of cells of \a this mesh. The
1085 * cells to include to the result mesh are specified by an array of cell ids.
1086 * <br> This method additionally returns a renumbering map in "Old to New" mode
1087 * which allows the caller to know the mapping between nodes in \a this and the result mesh.
1088 * \param [in] start - an array of cell ids to include to the result mesh.
1089 * \param [in] end - specifies the end of the array \a start, so that
1090 * the last value of \a start is \a end[ -1 ].
1091 * \param [out] arr - a new DataArrayInt that is the "Old to New" renumbering
1092 * map. The caller is to delete this array using decrRef() as it is no more needed.
1093 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
1094 * delete this mesh using decrRef() as it is no more needed.
1096 MEDCouplingMesh *MEDCouplingPointSet::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
1098 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelf(start,end,true);
1099 arr=ret->zipCoordsTraducer();
1104 * This method specialized the MEDCouplingMesh::buildPartRange.
1105 * This method is equivalent to MEDCouplingMesh::buildPart method except that here the cell ids are specified using slice
1106 * \a beginCellIds \a endCellIds and \a stepCellIds.
1107 * \b WARNING , there is a big difference compared to MEDCouplingMesh::buildPart method.
1108 * If the input range is equal all cells in \a this, \a this is returned !
1110 * \return a new ref to be managed by the caller. Warning this ref can be equal to \a this if input slice is exactly equal to the whole cells in the same order.
1112 * \sa MEDCouplingUMesh::buildPartOfMySelf2
1114 MEDCouplingMesh *MEDCouplingPointSet::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const
1116 if(beginCellIds==0 && endCellIds==getNumberOfCells() && stepCellIds==1)
1118 MEDCouplingMesh *ret(const_cast<MEDCouplingPointSet *>(this));
1124 return buildPartOfMySelf2(beginCellIds,endCellIds,stepCellIds,true);
1129 * This method specialized the MEDCouplingMesh::buildPartRangeAndReduceNodes
1131 * \param [out] beginOut valid only if \a arr not NULL !
1132 * \param [out] endOut valid only if \a arr not NULL !
1133 * \param [out] stepOut valid only if \a arr not NULL !
1134 * \param [out] arr correspondance old to new in node ids.
1136 * \sa MEDCouplingUMesh::buildPartOfMySelf2
1138 MEDCouplingMesh *MEDCouplingPointSet::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const
1140 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelf2(beginCellIds,endCellIds,stepCellIds,true);
1141 arr=ret->zipCoordsTraducer();
1146 * 'This' is expected to be of spaceDim==2. Idem for 'center' and 'vect'
1148 void MEDCouplingPointSet::rotate2D(const double *center, double angle)
1150 double *coords=_coords->getPointer();
1151 int nbNodes=getNumberOfNodes();
1152 Rotate2DAlg(center,angle,nbNodes,coords);
1156 * Low static method that operates 3D rotation of 'nbNodes' 3D nodes whose coordinates are arranged in 'coords'
1157 * around the center point 'center' and with angle 'angle'.
1159 void MEDCouplingPointSet::Rotate2DAlg(const double *center, double angle, int nbNodes, double *coords)
1161 double cosa=cos(angle);
1162 double sina=sin(angle);
1164 matrix[0]=cosa; matrix[1]=-sina; matrix[2]=sina; matrix[3]=cosa;
1166 for(int i=0; i<nbNodes; i++)
1168 std::transform(coords+i*2,coords+(i+1)*2,center,tmp,std::minus<double>());
1169 coords[i*2]=matrix[0]*tmp[0]+matrix[1]*tmp[1]+center[0];
1170 coords[i*2+1]=matrix[2]*tmp[0]+matrix[3]*tmp[1]+center[1];
1179 static const int MY_SPACEDIM=3;
1180 static const int MY_MESHDIM=2;
1181 typedef int MyConnType;
1182 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
1188 * res should be an empty vector before calling this method.
1189 * This method returns all the node coordinates included in _coords which ids are in [startConn;endConn) and put it into 'res' vector.
1190 * If spaceDim==3 a projection will be done for each nodes on the middle plane containing these all nodes in [startConn;endConn).
1191 * And after each projected nodes are moved to Oxy plane in order to consider these nodes as 2D nodes.
1193 void MEDCouplingPointSet::project2DCellOnXY(const int *startConn, const int *endConn, std::vector<double>& res) const
1195 const double *coords=_coords->getConstPointer();
1196 int spaceDim=getSpaceDimension();
1197 for(const int *it=startConn;it!=endConn;it++)
1198 res.insert(res.end(),coords+spaceDim*(*it),coords+spaceDim*(*it+1));
1203 std::vector<double> cpy(res);
1204 int nbNodes=(int)std::distance(startConn,endConn);
1205 INTERP_KERNEL::PlanarIntersector<DummyClsMCPS,int>::projection(&res[0],&cpy[0],nbNodes,nbNodes,1.e-12,0.,0.,true);
1206 res.resize(2*nbNodes);
1207 for(int i=0;i<nbNodes;i++)
1210 res[2*i+1]=cpy[3*i+1];
1214 throw INTERP_KERNEL::Exception("Invalid spacedim for project2DCellOnXY !");
1218 * low level method that checks that the 2D cell is not a butterfly cell.
1220 bool MEDCouplingPointSet::isButterfly2DCell(const std::vector<double>& res, bool isQuad, double eps)
1222 std::size_t nbOfNodes=res.size()/2;
1223 std::vector<INTERP_KERNEL::Node *> nodes(nbOfNodes);
1224 for(std::size_t i=0;i<nbOfNodes;i++)
1226 INTERP_KERNEL::Node *tmp=new INTERP_KERNEL::Node(res[2*i],res[2*i+1]);
1229 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
1230 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
1231 INTERP_KERNEL::QuadraticPolygon *pol=0;
1233 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
1235 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
1236 bool ret=pol->isButterflyAbs();
1242 * This method compares 2 cells coming from two unstructured meshes : \a this and \a other.
1243 * This method compares 2 cells having the same id 'cellId' in \a this and \a other.
1245 bool MEDCouplingPointSet::areCellsFrom2MeshEqual(const MEDCouplingPointSet *other, int cellId, double prec) const
1247 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1249 std::vector<int> c1,c2;
1250 getNodeIdsOfCell(cellId,c1);
1251 other->getNodeIdsOfCell(cellId,c2);
1252 std::size_t sz=c1.size();
1255 for(std::size_t i=0;i<sz;i++)
1257 std::vector<double> n1,n2;
1258 getCoordinatesOfNode(c1[0],n1);
1259 other->getCoordinatesOfNode(c2[0],n2);
1260 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1261 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1262 if(*std::max_element(n1.begin(),n1.end())>prec)
1269 * Substitutes node coordinates array of \a this mesh with that of \a other mesh
1270 * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
1271 * meshes match with a specified precision, else an exception is thrown and \a this
1272 * remains unchanged. In case of success the nodal connectivity of \a this mesh
1273 * is permuted according to new order of nodes.
1274 * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
1275 * coordinates (and so more expensive) than simple equality.
1276 * \param [in] other - the other mesh whose node coordinates array will be used by
1277 * \a this mesh in case of their equality.
1278 * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
1279 * \throw If the coordinates array of \a this is not set.
1280 * \throw If the coordinates array of \a other is not set.
1281 * \throw If the coordinates of \a this and \a other do not match.
1283 void MEDCouplingPointSet::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon)
1285 const DataArrayDouble *coords=other.getCoords();
1287 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in other !");
1289 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1290 int otherNbOfNodes=other.getNumberOfNodes();
1291 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1293 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1294 setCoords(newCoords);
1295 bool areNodesMerged;
1297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1300 setCoords(oldCoords);
1301 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1303 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1304 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1305 if(pt!=da->getConstPointer()+da->getNbOfElems())
1307 setCoords(oldCoords);
1308 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1310 setCoords(oldCoords);
1311 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1315 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1317 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords(begin,end);
1323 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords2(start,end,step);
1332 Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
1333 copy are selected basing on specified node ids and the value of \a fullyIn
1334 parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
1335 array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
1336 node is in the array of node ids. The created mesh shares the node coordinates array
1338 * \param [in] begin - the array of node ids.
1339 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
1340 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
1341 * array \a begin are copied, else cells whose any node is in the
1342 * array \a begin are copied.
1343 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
1344 * to delete this mesh using decrRef() as it is no more needed.
1345 * \throw If the coordinates array is not set.
1346 * \throw If the nodal connectivity of cells is not defined.
1347 * \throw If any node id in \a begin is not valid.
1349 * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
1350 * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
1352 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1354 DataArrayInt *cellIdsKept=0;
1355 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
1357 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
1361 * Removes duplicates of cells from \a this mesh and returns an array mapping between
1362 * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1363 * equal cells found.
1364 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1365 * to write this mesh to the MED file, its cells must be sorted using
1366 * sortCellsInMEDFileFrmt().
1367 * \param [in] compType - specifies a cell comparison technique. Meaning of its
1368 * valid values [0,1,2] is as follows.
1369 * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1370 * connectivity and type. This is the strongest policy.
1371 * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1372 * are based on same nodes and have the same type and orientation.
1373 * - 2 : "nodal". Two cells are considered equal \c iff they
1374 * are based on same nodes and have the same type. This is the weakest
1375 * policy, it can be used by users not sensitive to cell orientation.
1376 * \param [in] startCellId - specifies the cell id at which search for equal cells
1377 * starts. By default it is 0, which means that all cells in \a this will be
1379 * \return DataArrayInt - a new instance of DataArrayInt, of length \a
1380 * this->getNumberOfCells() before call of this method. The caller is to
1381 * delete this array using decrRef() as it is no more needed.
1382 * \throw If the coordinates array is not set.
1383 * \throw If the nodal connectivity of cells is not defined.
1384 * \throw If the nodal connectivity includes an invalid id.
1386 * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1387 * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1389 DataArrayInt *MEDCouplingPointSet::zipConnectivityTraducer(int compType, int startCellId)
1391 DataArrayInt *commonCells=0,*commonCellsI=0;
1392 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1394 int newNbOfCells=-1;
1395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1396 commonCellsI->end(),newNbOfCells);
1397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> self=buildPartOfMySelf(ret2->begin(),ret2->end(),true);
1399 shallowCopyConnectivityFrom(self);
1404 * Checks if \a this and \a other meshes are geometrically equivalent, else an
1405 * exception is thrown. The meshes are
1406 * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
1407 * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
1408 * the \a other mesh (with use of a specified cell comparison technique). The mapping
1409 * from \a other to \a this for nodes and cells is returned via out parameters.
1410 * \param [in] other - the mesh to compare with.
1411 * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
1412 * each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
1413 * \param [in] prec - the precision used to compare nodes of the two meshes.
1414 * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
1415 * to delete this array using decrRef() as it is no more needed.
1416 * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
1417 * to delete this array using decrRef() as it is no more needed.
1418 * \throw If the two meshes do not match.
1420 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
1421 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
1423 void MEDCouplingPointSet::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
1424 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
1427 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : input is null !");
1428 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1430 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : other is not a PointSet mesh !");
1431 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m=dynamic_cast<MEDCouplingPointSet *>(mergeMyselfWith(otherC));
1432 bool areNodesMerged;
1434 int oldNbOfNodes=getNumberOfNodes();
1435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
1438 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
1439 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
1440 if(pt!=da->getConstPointer()+da->getNbOfElems())
1441 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
1442 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
1444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
1445 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
1447 da=m->zipConnectivityTraducer(cellCompPol);
1448 int nbCells=getNumberOfCells();
1451 maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
1452 pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1453 if(pt!=da->getConstPointer()+da->getNbOfElems())
1454 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
1455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
1456 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
1457 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
1461 * Checks if \a this and \a other meshes are geometrically equivalent, else an
1462 * exception is thrown. The meshes are considered equivalent if (1) they share one
1463 * node coordinates array and (2) they contain the same cells (with use of a specified
1464 * cell comparison technique). The mapping from cells of the \a other to ones of \a this
1465 * is returned via an out parameter.
1466 * \param [in] other - the mesh to compare with.
1467 * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
1468 * each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
1469 * \param [in] prec - a not used parameter.
1470 * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
1471 * to delete this array using decrRef() as it is no more needed.
1472 * \throw If the two meshes do not match.
1474 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
1475 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
1477 void MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
1478 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
1481 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : input is null !");
1482 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1484 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : other is not a PointSet mesh !");
1485 if(_coords!=otherC->_coords)
1486 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
1487 MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m=mergeMyselfWithOnSameCoords(otherC);
1488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
1489 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
1490 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1491 if(pt!=da->getConstPointer()+da->getNbOfElems())
1493 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
1495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
1496 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
1499 void MEDCouplingPointSet::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
1501 MEDCouplingMesh::checkFastEquivalWith(other,prec);
1502 //other not null checked by the line before
1503 const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1505 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkFastEquivalWith : fails because other is not a pointset mesh !");
1506 int nbOfCells=getNumberOfCells();
1510 status&=areCellsFrom2MeshEqual(otherC,0,prec);
1511 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
1512 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
1514 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
1518 * Finds cells whose all or some nodes are in a given array of node ids.
1519 * \param [in] begin - the array of node ids.
1520 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
1521 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
1522 * array \a begin are returned only, else cells whose any node is in the
1523 * array \a begin are returned.
1524 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
1525 * cells. The caller is to delete this array using decrRef() as it is no more
1527 * \throw If the coordinates array is not set.
1528 * \throw If the nodal connectivity of cells is not defined.
1529 * \throw If any cell id in \a begin is not valid.
1531 * \sa MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds
1533 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
1534 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
1536 DataArrayInt *MEDCouplingPointSet::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1538 DataArrayInt *cellIdsKept=0;
1539 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1540 cellIdsKept->setName(getName());
1545 * Finds cells whose all nodes are in a given array of node ids.
1546 * This method is a specialization of MEDCouplingPointSet::getCellIdsLyingOnNodes (true
1547 * as last input argument).
1548 * \param [in] partBg - the array of node ids.
1549 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
1550 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
1551 * cells. The caller is to delete this array using decrRef() as it is no
1553 * \throw If the coordinates array is not set.
1554 * \throw If the nodal connectivity of cells is not defined.
1555 * \throw If any cell id in \a partBg is not valid.
1557 * \sa MEDCouplingPointSet::getCellIdsLyingOnNodes
1559 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
1560 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
1562 DataArrayInt *MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1564 return getCellIdsLyingOnNodes(partBg,partEnd,true);
1568 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1569 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1570 * array mean that the corresponding old node is no more used.
1571 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1572 * this->getNumberOfNodes() before call of this method. The caller is to
1573 * delete this array using decrRef() as it is no more needed.
1574 * \throw If the coordinates array is not set.
1575 * \throw If the nodal connectivity of cells is not defined.
1576 * \throw If the nodal connectivity includes an invalid id.
1578 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1579 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1581 DataArrayInt *MEDCouplingPointSet::zipCoordsTraducer()
1583 int newNbOfNodes=-1;
1584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> traducer=getNodeIdsInUse(newNbOfNodes);
1585 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1586 return traducer.retn();
1590 * Merges nodes equal within \a precision and returns an array describing the
1591 * permutation used to remove duplicate nodes.
1592 * \param [in] precision - minimal absolute distance between two nodes at which they are
1593 * considered not coincident.
1594 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1595 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1596 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1597 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1598 * is to delete this array using decrRef() as it is no more needed.
1599 * \throw If the coordinates array is not set.
1600 * \throw If the nodal connectivity of cells is not defined.
1602 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1603 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1605 DataArrayInt *MEDCouplingPointSet::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1607 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1609 renumberNodes(ret->begin(),newNbOfNodes);
1614 * Merges nodes equal within \a precision and returns an array describing the
1615 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1616 * of merged nodes is changed to be at their barycenter.
1617 * \param [in] precision - minimal absolute distance between two nodes at which they are
1618 * considered not coincident.
1619 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1620 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1621 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1622 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1623 * is to delete this array using decrRef() as it is no more needed.
1624 * \throw If the coordinates array is not set.
1625 * \throw If the nodal connectivity of cells is not defined.
1627 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1628 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1630 DataArrayInt *MEDCouplingPointSet::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1632 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1634 renumberNodes2(ret->getConstPointer(),newNbOfNodes);