From f1a45b868dcdee1834250cbbede3d62d452ddac9 Mon Sep 17 00:00:00 2001 From: "eduardo.davila@creatis.insa-lyon.fr" Date: Tue, 17 Jun 2025 15:19:34 +0200 Subject: [PATCH] #3534 MeshFromPoints MeshToImageData --- bbtk_creaVtk_PKG/.DS_Store | Bin 8196 -> 8196 bytes .../src/bbcreaVtkCreateMeshFromPoints.cxx | 856 +++++++++--------- .../src/bbcreaVtkCreateMeshFromPoints.h | 1 - .../src/bbcreaVtkMarchingCubes2.h | 4 +- .../src/bbcreaVtkPolyDataToImageData.h | 3 +- .../src/bbcreaVtkScalarsToColors.cxx | 2 + lib/creaVtk/MeshFromPoints.cpp | 456 ++++++++++ lib/creaVtk/MeshFromPoints.h | 67 ++ lib/creaVtk/MeshToImageData.cpp | 85 ++ lib/creaVtk/MeshToImageData.h | 52 ++ 10 files changed, 1092 insertions(+), 434 deletions(-) create mode 100644 lib/creaVtk/MeshFromPoints.cpp create mode 100644 lib/creaVtk/MeshFromPoints.h create mode 100644 lib/creaVtk/MeshToImageData.cpp create mode 100644 lib/creaVtk/MeshToImageData.h diff --git a/bbtk_creaVtk_PKG/.DS_Store b/bbtk_creaVtk_PKG/.DS_Store index 8fd3482ce295b13412c4a47a718c628794e1ca1a..afa815535c7de6d6e2d9472d3384e822300392fe 100644 GIT binary patch delta 14 VcmZp1XmQx^U67Gs^AABDJ^(9B1sDJT delta 14 VcmZp1XmQx^U67G+^AABDJ^(9H1sMPU diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.cxx b/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.cxx index 2a4dd44..0009dd1 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.cxx +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.cxx @@ -13,475 +13,473 @@ namespace bbcreaVtk BBTK_ADD_BLACK_BOX_TO_PACKAGE(creaVtk,CreateMeshFromPoints) BBTK_BLACK_BOX_IMPLEMENTATION(CreateMeshFromPoints,bbtk::AtomicBlackBox); -//===== +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) -//===== +//===== void CreateMeshFromPoints::Process() { - -// THE MAIN PROCESSING METHOD BODY -// Here we simply set the input 'In' value to the output 'Out' -// And print out the output value -// INPUT/OUTPUT ACCESSORS ARE OF THE FORM : -// void bbSet{Input|Output}NAME(const TYPE&) -// const TYPE& bbGet{Input|Output}NAME() const -// Where : -// * NAME is the name of the input/output -// (the one provided in the attribute 'name' of the tag 'input') -// * TYPE is the C++ type of the input/output -// (the one provided in the attribute 'type' of the tag 'input') - -// bbSetOutputOut( bbGetInputIn() ); -// std::cout << "Output value = " < lstX = bbGetInputLstX(); - std::vector lstY = bbGetInputLstY(); - std::vector lstZ = bbGetInputLstZ(); - std::vector lstIndexs = bbGetInputLstIndexs(); - double pointsCentroid[3]; - if ( (lstIndexs.size()<1) || (lstX.size()==0) || (lstX.size()!=lstY.size()) || (lstY.size()!=lstZ.size()) ) - { - printf("Warning! CreateMeshFromPoints::Process: List of points X Y Z and LstIndexes is not correct\n"); - bbSetOutputOut(NULL); - } else { - int ii,sizeSegment1,sizeSegment2; - int endSegment; -// vtkSmartPointer points = vtkSmartPointer::New(); - if (points!=NULL) points->Delete(); - points = vtkPoints::New(); - int i,sizeLstX = lstX.size(); - for (i=0;iInsertNextPoint(lstX[i],lstY[i],lstZ[i]); - pointsCentroid[0] += lstX[i]; - pointsCentroid[1] += lstY[i]; - pointsCentroid[2] += lstZ[i]; - } // for i - pointsCentroid[0] /= sizeLstX; - pointsCentroid[1] /= sizeLstX; - pointsCentroid[2] /= sizeLstX; - - if ((bbGetInputCloseSurface()==true) && (lstIndexs.size()>=2) ) - { - //check if initial and end points are the same in all splines (splines are in line shape and not U shape) - //to not apply changes because clean polydata will take care of it. - int count = 0; - bool differentPoints = false; - for(i=0; i < lstIndexs.size() && !differentPoints;i++){ - bool sameStart = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; - bool sameEnd = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; - if(!(sameStart && sameEnd)) differentPoints = true; - count += lstIndexs[i]; - } - //Correct surface normals if needed - if(differentPoints) - { - double pointSurf1[3], pointSurf2[3], pointSurf3[3]; - double vect1[3], vect2[3]; - double surfNormal[3], vectorCenter[3]; - double dotNormalSurf = 0; - for(int pIndex = 0; pIndex < lstIndexs[0]-1; pIndex++) - { - pointSurf1[0] = lstX[pIndex]; - pointSurf1[1] = lstY[pIndex]; - pointSurf1[2] = lstZ[pIndex]; - vtkMath::Subtract(pointsCentroid, pointSurf1, vectorCenter); - pointSurf2[0] = lstX[pIndex+lstIndexs[1]]; - pointSurf2[1] = lstY[pIndex+lstIndexs[1]]; - pointSurf2[2] = lstZ[pIndex+lstIndexs[1]]; - pointSurf3[0] = lstX[pIndex+1]; - pointSurf3[1] = lstY[pIndex+1]; - pointSurf3[2] = lstZ[pIndex+1]; - vtkMath::Subtract(pointSurf2, pointSurf1, vect1); - vtkMath::Subtract(pointSurf3, pointSurf1, vect2); - vtkMath::Cross(vect1, vect2, surfNormal); - dotNormalSurf += vtkMath::Dot(surfNormal, vectorCenter); - } // for pIndex - - if(dotNormalSurf > 0){ - points->Delete(); - points = vtkPoints::New(); - for(int splineI = 0; splineI < lstIndexs.size(); splineI++){ - for (i=lstIndexs[splineI]-1; i >= 0;i--) - { - points->InsertNextPoint(lstX[splineI*lstIndexs[0]+i],lstY[splineI*lstIndexs[0]+i],lstZ[splineI*lstIndexs[0]+i]); - } // for i - } // for splineI - } // if dotNormalSurf - }// if differentPoints - } - // - -// vtkSmartPointer cells = vtkSmartPointer::New(); - if (cells!=NULL) cells->Delete(); - cells = vtkCellArray::New(); - int maxElements; - int maxSegment1,maxSegment2; - int iSeg1,iSeg2; - int iGeneral = 0; - int sizeLstIdexes=lstIndexs.size(); - for (i=0; i triangleStrip = vtkSmartPointer::New(); - triangleStrip->GetPointIds()->SetNumberOfIds(sizeSegment1+sizeSegment2); - maxElements=sizeSegment1; - if (maxElementsGetPointIds()->SetId(ii*2 ,iSeg1); - triangleStrip->GetPointIds()->SetId(ii*2+1,iSeg2); - iSeg1++; - iSeg2++; - if (iSeg1>=maxSegment1) { iSeg1=maxSegment1-1; } - if (iSeg2>=maxSegment2) { iSeg2=maxSegment2-1; } - } // for ii - iGeneral=iGeneral+sizeSegment1; - cells->InsertNextCell(triangleStrip); - } //for LstIndexs - - - if(bbGetInputCloseSurface()) - { - int lastId1 = lstIndexs[0]-1; - int lastId2 = sizeLstX - 1; - int firstId2 = sizeLstX - lstIndexs[sizeLstIdexes - 1]; - bool face1open = std::fabs(lstX[0] - lstX[lastId1]) > 0.0001 || std::fabs(lstY[0] - lstY[lastId1]) > 0.0001 || std::fabs(lstZ[0] - lstZ[lastId1]) > 0.0001; - bool face2open = std::fabs(lstX[firstId2] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[firstId2] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[firstId2] - lstZ[lastId2]) > 0.0001; - - bool altFace1open = std::fabs(lstX[0] - lstX[firstId2]) > 0.0001 || std::fabs(lstY[0] - lstY[firstId2]) > 0.0001 || std::fabs(lstZ[0] - lstZ[firstId2]) > 0.0001; - bool altFace2open = std::fabs(lstX[lastId1] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[lastId1] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[lastId1] - lstZ[lastId2]) > 0.0001; - - //false = Open Contour - //true = Closed Contour - if(!face1open && !face2open) - { -// isClosedCont = true; - CloseContourSides(lstIndexs, true, true); - } - else if(!altFace1open && !altFace2open) - { -// isClosedCont = true; - CloseContourSides(lstIndexs, false, true); - } - else{ - CloseOpenContourSurface(lstIndexs); - } - } - -// vtkPolyData *polydata = vtkPolyData::New(); - if (polydata!=NULL) polydata->Delete(); - polydata = vtkPolyData::New(); - polydata->SetPoints(points); - polydata->SetStrips(cells); -// vtkCleanPolyData *clean=vtkCleanPolyData::New(); - if (clean!=NULL) clean->Delete(); - clean = vtkCleanPolyData::New(); - clean->SetInputData(polydata); - clean->Update(); -// vtkTriangleFilter *triangle = vtkTriangleFilter::New(); - if (triangle!=NULL) triangle->Delete(); - triangle = vtkTriangleFilter::New(); - triangle->SetInputData( clean->GetOutput() ); - triangle->Update(); - bbSetOutputOut( triangle->GetOutput() ); - // bbSetOutputOut( clean->GetOutput() ); - }// if listXYZ size - //printf("PG CreateMeshFromPoints::Process: End\n"); + + // THE MAIN PROCESSING METHOD BODY + // Here we simply set the input 'In' value to the output 'Out' + // And print out the output value + // INPUT/OUTPUT ACCESSORS ARE OF THE FORM : + // void bbSet{Input|Output}NAME(const TYPE&) + // const TYPE& bbGet{Input|Output}NAME() const + // Where : + // * NAME is the name of the input/output + // (the one provided in the attribute 'name' of the tag 'input') + // * TYPE is the C++ type of the input/output + // (the one provided in the attribute 'type' of the tag 'input') + + // bbSetOutputOut( bbGetInputIn() ); + // std::cout << "Output value = " < lstX = bbGetInputLstX(); + std::vector lstY = bbGetInputLstY(); + std::vector lstZ = bbGetInputLstZ(); + std::vector lstIndexs = bbGetInputLstIndexs(); + double pointsCentroid[3]; + if ( (lstIndexs.size()<1) || (lstX.size()==0) || (lstX.size()!=lstY.size()) || (lstY.size()!=lstZ.size()) ) + { + printf("Warning! CreateMeshFromPoints::Process: List of points X Y Z and LstIndexes is not correct\n"); + bbSetOutputOut(NULL); + } else { + int ii,sizeSegment1,sizeSegment2; + int endSegment; + // vtkSmartPointer points = vtkSmartPointer::New(); + if (points!=NULL) points->Delete(); + points = vtkPoints::New(); + int i,sizeLstX = lstX.size(); + for (i=0;iInsertNextPoint(lstX[i],lstY[i],lstZ[i]); + pointsCentroid[0] += lstX[i]; + pointsCentroid[1] += lstY[i]; + pointsCentroid[2] += lstZ[i]; + } // for i + pointsCentroid[0] /= sizeLstX; + pointsCentroid[1] /= sizeLstX; + pointsCentroid[2] /= sizeLstX; + + if ((bbGetInputCloseSurface()==true) && (lstIndexs.size()>=2) ) + { + //check if initial and end points are the same in all splines (splines are in line shape and not U shape) + //to not apply changes because clean polydata will take care of it. + int count = 0; + bool differentPoints = false; + for(i=0; i < lstIndexs.size() && !differentPoints;i++){ + bool sameStart = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; + bool sameEnd = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; + if(!(sameStart && sameEnd)) differentPoints = true; + count += lstIndexs[i]; + } + //Correct surface normals if needed + if(differentPoints) + { + double pointSurf1[3], pointSurf2[3], pointSurf3[3]; + double vect1[3], vect2[3]; + double surfNormal[3], vectorCenter[3]; + double dotNormalSurf = 0; + for(int pIndex = 0; pIndex < lstIndexs[0]-1; pIndex++) + { + pointSurf1[0] = lstX[pIndex]; + pointSurf1[1] = lstY[pIndex]; + pointSurf1[2] = lstZ[pIndex]; + vtkMath::Subtract(pointsCentroid, pointSurf1, vectorCenter); + pointSurf2[0] = lstX[pIndex+lstIndexs[1]]; + pointSurf2[1] = lstY[pIndex+lstIndexs[1]]; + pointSurf2[2] = lstZ[pIndex+lstIndexs[1]]; + pointSurf3[0] = lstX[pIndex+1]; + pointSurf3[1] = lstY[pIndex+1]; + pointSurf3[2] = lstZ[pIndex+1]; + vtkMath::Subtract(pointSurf2, pointSurf1, vect1); + vtkMath::Subtract(pointSurf3, pointSurf1, vect2); + vtkMath::Cross(vect1, vect2, surfNormal); + dotNormalSurf += vtkMath::Dot(surfNormal, vectorCenter); + } // for pIndex + + if(dotNormalSurf > 0){ + points->Delete(); + points = vtkPoints::New(); + for(int splineI = 0; splineI < lstIndexs.size(); splineI++){ + for (i=lstIndexs[splineI]-1; i >= 0;i--) + { + points->InsertNextPoint(lstX[splineI*lstIndexs[0]+i],lstY[splineI*lstIndexs[0]+i],lstZ[splineI*lstIndexs[0]+i]); + } // for i + } // for splineI + } // if dotNormalSurf + }// if differentPoints + } + // + + // vtkSmartPointer cells = vtkSmartPointer::New(); + if (cells!=NULL) cells->Delete(); + cells = vtkCellArray::New(); + int maxElements; + int maxSegment1,maxSegment2; + int iSeg1,iSeg2; + int iGeneral = 0; + int sizeLstIdexes=lstIndexs.size(); + for (i=0; i triangleStrip = vtkSmartPointer::New(); + triangleStrip->GetPointIds()->SetNumberOfIds(sizeSegment1+sizeSegment2); + maxElements=sizeSegment1; + if (maxElementsGetPointIds()->SetId(ii*2 ,iSeg1); + triangleStrip->GetPointIds()->SetId(ii*2+1,iSeg2); + iSeg1++; + iSeg2++; + if (iSeg1>=maxSegment1) { iSeg1=maxSegment1-1; } + if (iSeg2>=maxSegment2) { iSeg2=maxSegment2-1; } + } // for ii + iGeneral=iGeneral+sizeSegment1; + cells->InsertNextCell(triangleStrip); + } //for LstIndexs + + + if(bbGetInputCloseSurface()) + { + int lastId1 = lstIndexs[0]-1; + int lastId2 = sizeLstX - 1; + int firstId2 = sizeLstX - lstIndexs[sizeLstIdexes - 1]; + bool face1open = std::fabs(lstX[0] - lstX[lastId1]) > 0.0001 || std::fabs(lstY[0] - lstY[lastId1]) > 0.0001 || std::fabs(lstZ[0] - lstZ[lastId1]) > 0.0001; + bool face2open = std::fabs(lstX[firstId2] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[firstId2] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[firstId2] - lstZ[lastId2]) > 0.0001; + + bool altFace1open = std::fabs(lstX[0] - lstX[firstId2]) > 0.0001 || std::fabs(lstY[0] - lstY[firstId2]) > 0.0001 || std::fabs(lstZ[0] - lstZ[firstId2]) > 0.0001; + bool altFace2open = std::fabs(lstX[lastId1] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[lastId1] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[lastId1] - lstZ[lastId2]) > 0.0001; + + //false = Open Contour + //true = Closed Contour + if(!face1open && !face2open) + { + // isClosedCont = true; + CloseContourSides(lstIndexs, true, true); + } + else if(!altFace1open && !altFace2open) + { + // isClosedCont = true; + CloseContourSides(lstIndexs, false, true); + } + else{ + CloseOpenContourSurface(lstIndexs); + } + } + + // vtkPolyData *polydata = vtkPolyData::New(); + if (polydata!=NULL) polydata->Delete(); + polydata = vtkPolyData::New(); + polydata->SetPoints(points); + polydata->SetStrips(cells); + // vtkCleanPolyData *clean=vtkCleanPolyData::New(); + if (clean!=NULL) clean->Delete(); + clean = vtkCleanPolyData::New(); + clean->SetInputData(polydata); + clean->Update(); + // vtkTriangleFilter *triangle = vtkTriangleFilter::New(); + if (triangle!=NULL) triangle->Delete(); + triangle = vtkTriangleFilter::New(); + triangle->SetInputData( clean->GetOutput() ); + triangle->Update(); + bbSetOutputOut( triangle->GetOutput() ); + // bbSetOutputOut( clean->GetOutput() ); + }// if listXYZ size + //printf("PG CreateMeshFromPoints::Process: End\n"); } /** -* Closes the sides of the contour -* iterates in one way or the other, depending on the order of the points and calculated vectors. -* uPointOrder: Points are order in a U shape -* lstIndexs: number of points on each spline -*/ + * Closes the sides of the contour + * iterates in one way or the other, depending on the order of the points and calculated vectors. + * uPointOrder: Points are order in a U shape + * lstIndexs: number of points on each spline + */ void CreateMeshFromPoints::CloseContourSides(std::vector lstIndexs, bool uPointOrder, bool isClosedCont){ - int sizeLstIdexes = lstIndexs.size(); - int sizePoints = bbGetInputLstX().size(); - - int firstIndex, end, centroidId, numPointsFace, contraryId; - int increment = uPointOrder?1:sizeLstIdexes; - double centroid[3]; - int numProcessFaces = sizeLstIdexes > 1?2:1; - for(int facesIdx = 0; facesIdx < numProcessFaces; facesIdx++){ - std::fill(std::begin(centroid), std::end(centroid), 0); - if(facesIdx == 0) - { - firstIndex = 0; - numPointsFace = uPointOrder?lstIndexs[0]: sizeLstIdexes; - end = uPointOrder?firstIndex + numPointsFace:sizePoints - lstIndexs[sizeLstIdexes - 1] + 1; - contraryId = sizePoints-1; - }else{ - firstIndex = uPointOrder?sizePoints - lstIndexs[sizeLstIdexes-1]:lstIndexs[0]-1; - numPointsFace = uPointOrder?lstIndexs[sizeLstIdexes-1]:sizeLstIdexes; - end = uPointOrder?firstIndex + numPointsFace:sizePoints; - contraryId = 0; - } - if(numPointsFace > 1) - { - bool validCentroid = CalcValidCentroid(centroid, firstIndex, end, increment, numPointsFace); - if(validCentroid) - { - bool normalOrder = isPointingCorrectly(firstIndex, firstIndex+increment, centroid, contraryId); - centroidId = points->InsertNextPoint(centroid[0], centroid[1], centroid[2]); - //vtkSmartPointer triangleStrip = vtkSmartPointer::New(); - //triangleStrip->GetPointIds()->SetNumberOfIds(numPointsFace*2 + (!isClosedCont?2:0)); - //int triangleIndex = 0; - if( normalOrder ) + int sizeLstIdexes = lstIndexs.size(); + int sizePoints = bbGetInputLstX().size(); + + int firstIndex, end, centroidId, numPointsFace, contraryId; + int increment = uPointOrder?1:sizeLstIdexes; + double centroid[3]; + int numProcessFaces = sizeLstIdexes > 1?2:1; + for(int facesIdx = 0; facesIdx < numProcessFaces; facesIdx++){ + std::fill(std::begin(centroid), std::end(centroid), 0); + if(facesIdx == 0) + { + firstIndex = 0; + numPointsFace = uPointOrder?lstIndexs[0]: sizeLstIdexes; + end = uPointOrder?firstIndex + numPointsFace:sizePoints - lstIndexs[sizeLstIdexes - 1] + 1; + contraryId = sizePoints-1; + }else{ + firstIndex = uPointOrder?sizePoints - lstIndexs[sizeLstIdexes-1]:lstIndexs[0]-1; + numPointsFace = uPointOrder?lstIndexs[sizeLstIdexes-1]:sizeLstIdexes; + end = uPointOrder?firstIndex + numPointsFace:sizePoints; + contraryId = 0; + } + if(numPointsFace > 1) + { + bool validCentroid = CalcValidCentroid(centroid, firstIndex, end, increment, numPointsFace); + if(validCentroid) + { + bool normalOrder = isPointingCorrectly(firstIndex, firstIndex+increment, centroid, contraryId); + centroidId = points->InsertNextPoint(centroid[0], centroid[1], centroid[2]); + //vtkSmartPointer triangleStrip = vtkSmartPointer::New(); + //triangleStrip->GetPointIds()->SetNumberOfIds(numPointsFace*2 + (!isClosedCont?2:0)); + //int triangleIndex = 0; + if( normalOrder ) { - int initial = firstIndex; - for(int index = initial; index < end; index+=increment){ - if(index+increment >= end && !isClosedCont){ - vtkNew triangle; - triangle->GetPointIds()->SetId(0, index); - triangle->GetPointIds()->SetId(1, initial); - triangle->GetPointIds()->SetId(2, centroidId); - cells->InsertNextCell(triangle); - }else if(index+increment < end){ - vtkNew triangle; - triangle->GetPointIds()->SetId(0, index); - triangle->GetPointIds()->SetId(1, index+increment); - triangle->GetPointIds()->SetId(2, centroidId); - cells->InsertNextCell(triangle); - } - /* - triangleStrip->GetPointIds()->SetId(triangleIndex,index); - triangleStrip->GetPointIds()->SetId(triangleIndex+1,centroidId);//1 - if(index+increment >= end && !isClosedCont){ - triangleStrip->GetPointIds()->SetId(triangleIndex+2,initial);//2 - triangleStrip->GetPointIds()->SetId(triangleIndex+3,centroidId);//3 - } - triangleIndex+=2; - */ - } - //cells->InsertNextCell(triangleStrip); - } else { - int initial = firstIndex-1; - int triangleStripStart = end-1; - for(int index = triangleStripStart; index > initial; index-=increment){ - if(index-increment <= initial && !isClosedCont){ - vtkNew triangle; - triangle->GetPointIds()->SetId(0, index); - triangle->GetPointIds()->SetId(1, triangleStripStart); - triangle->GetPointIds()->SetId(2, centroidId); - cells->InsertNextCell(triangle); - }else if(index-increment > initial){ - vtkNew triangle; - triangle->GetPointIds()->SetId(0, index); - triangle->GetPointIds()->SetId(1, index-increment); - triangle->GetPointIds()->SetId(2, centroidId); - cells->InsertNextCell(triangle); - } - } - }//if normalOrder - }//if validCentroid - }//if numPointsFace - }//for facesIdx - + int initial = firstIndex; + for(int index = initial; index < end; index+=increment){ + if(index+increment >= end && !isClosedCont){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, initial); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + }else if(index+increment < end){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, index+increment); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + } + /* + triangleStrip->GetPointIds()->SetId(triangleIndex,index); + triangleStrip->GetPointIds()->SetId(triangleIndex+1,centroidId);//1 + if(index+increment >= end && !isClosedCont){ + triangleStrip->GetPointIds()->SetId(triangleIndex+2,initial);//2 + triangleStrip->GetPointIds()->SetId(triangleIndex+3,centroidId);//3 + } + triangleIndex+=2; + */ + } + //cells->InsertNextCell(triangleStrip); + } else { + int initial = firstIndex-1; + int triangleStripStart = end-1; + for(int index = triangleStripStart; index > initial; index-=increment){ + if(index-increment <= initial && !isClosedCont){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, triangleStripStart); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + }else if(index-increment > initial){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, index-increment); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + } + } + }//if normalOrder + }//if validCentroid + }//if numPointsFace + }//for facesIdx + } /** -* Checks if the normal from firstPointId, secPointId and centroid points away -* from the vector centroid to contrPointId. -* Used to check that the order used to create the new polygons is correct. -*/ + * Checks if the normal from firstPointId, secPointId and centroid points away + * from the vector centroid to contrPointId. + * Used to check that the order used to create the new polygons is correct. + */ bool CreateMeshFromPoints::isPointingCorrectly( int firstPointId, int secPointId, double(¢roid)[3], int contrPointId) { - - double firstPoint[3], secPoint[3], contrPoint[3]; - points->GetPoint(firstPointId, firstPoint); - points->GetPoint(secPointId, secPoint); - - double firstVect[3], secVect[3], normal[3], contrVect[3]; - - vtkMath::Subtract(firstPoint, centroid, firstVect); - vtkMath::Subtract(secPoint, centroid, secVect); - - points->GetPoint(contrPointId, contrPoint); - vtkMath::Subtract(contrPoint, centroid, contrVect); - - vtkMath::Cross(firstVect, secVect, normal); - double dotCalc; - dotCalc = vtkMath::Dot(normal, contrVect); - - return dotCalc<0; + + double firstPoint[3], secPoint[3], contrPoint[3]; + points->GetPoint(firstPointId, firstPoint); + points->GetPoint(secPointId, secPoint); + + double firstVect[3], secVect[3], normal[3], contrVect[3]; + + vtkMath::Subtract(firstPoint, centroid, firstVect); + vtkMath::Subtract(secPoint, centroid, secVect); + + points->GetPoint(contrPointId, contrPoint); + vtkMath::Subtract(contrPoint, centroid, contrVect); + + vtkMath::Cross(firstVect, secVect, normal); + double dotCalc; + dotCalc = vtkMath::Dot(normal, contrVect); + + return dotCalc<0; } /** -* Checks if the order of the points represent a curved spline (U shape) or the points resemble a straight spline. -* Now it checks the angle between each point and the vector that goes from the last point to the first. -* -* Previous version checked the curvature between 3 points in the spline, but this created problems when the straight lines -* had curves in the middle, increasing the curvature although they are not in the U shape. -*/ + * Checks if the order of the points represent a curved spline (U shape) or the points resemble a straight spline. + * Now it checks the angle between each point and the vector that goes from the last point to the first. + * + * Previous version checked the curvature between 3 points in the spline, but this created problems when the straight lines + * had curves in the middle, increasing the curvature although they are not in the U shape. + */ bool CreateMeshFromPoints::CheckLinePointOrder(){ - int sizePoints = bbGetInputLstX().size(); - std::vector lstIndexs = bbGetInputLstIndexs(); - double point1[3], point2[3], point3[3]; - double center[3]; - double firstAngleSum = 0; - double secondAngleSum = 0; - - points->GetPoint(0, point1); - points->GetPoint((lstIndexs[0]-1), point3); - double firstVect[3]; - double secVect[3]; - vtkMath::Subtract(point3, point1, firstVect); - for(int i = 0; i < lstIndexs[0]; i++){ - points->GetPoint(i, point2); - vtkMath::Subtract(point2, point1, secVect); - firstAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); - } - points->GetPoint((sizePoints-lstIndexs[0]), point3); - vtkMath::Subtract(point3, point1, firstVect); - for(int i = 0; i < sizePoints; i+=lstIndexs.size()){ - points->GetPoint(i, point2); - vtkMath::Subtract(point2, point1, secVect); - secondAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); - } - - return firstAngleSum < secondAngleSum; + int sizePoints = bbGetInputLstX().size(); + std::vector lstIndexs = bbGetInputLstIndexs(); + double point1[3], point2[3], point3[3]; + double center[3]; + double firstAngleSum = 0; + double secondAngleSum = 0; + + points->GetPoint(0, point1); + points->GetPoint((lstIndexs[0]-1), point3); + double firstVect[3]; + double secVect[3]; + vtkMath::Subtract(point3, point1, firstVect); + for(int i = 0; i < lstIndexs[0]; i++){ + points->GetPoint(i, point2); + vtkMath::Subtract(point2, point1, secVect); + firstAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); + } + points->GetPoint((sizePoints-lstIndexs[0]), point3); + vtkMath::Subtract(point3, point1, firstVect); + for(int i = 0; i < sizePoints; i+=lstIndexs.size()){ + points->GetPoint(i, point2); + vtkMath::Subtract(point2, point1, secVect); + secondAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); + } + + return firstAngleSum < secondAngleSum; } /** -* Closes an open contour -* lstIndexs: number of points on each spline -*/ + * Closes an open contour + * lstIndexs: number of points on each spline + */ void CreateMeshFromPoints::CloseOpenContourSurface(std::vector lstIndexs){ - bool linePointOrder = CheckLinePointOrder(); - CloseContourSides(lstIndexs, !linePointOrder, false); - CloseContourBottom(!linePointOrder); + bool linePointOrder = CheckLinePointOrder(); + CloseContourSides(lstIndexs, !linePointOrder, false); + CloseContourBottom(!linePointOrder); } /** -* Calculates centroid and checks if points are collinear. -* centroid: array to store calculation -* start: start index of points to use -* end: end index of points to use -* increment: increment to be used in point iteration -* numPoints: number of points used to calculate the centroid. -* Returns a bool indicating the validity of the centroid calculated. -* False = invalid centroid = all points are the same. -*/ + * Calculates centroid and checks if points are collinear. + * centroid: array to store calculation + * start: start index of points to use + * end: end index of points to use + * increment: increment to be used in point iteration + * numPoints: number of points used to calculate the centroid. + * Returns a bool indicating the validity of the centroid calculated. + * False = invalid centroid = all points are the same. + */ bool CreateMeshFromPoints::CalcValidCentroid(double(¢roid)[3], int start, int end, int increment, int numPoints){ - double currPoint[3] = {}, prevPoint[3] = {}, middlePoint[3] = {}, firstPoint[3] = {}; - double vector1[3], vector2[3]; - bool samePoint = true; - int splineMidPoint = numPoints/2; - bool collinear = true; - - points->GetPoint(start, firstPoint); - points->GetPoint(splineMidPoint, middlePoint); - vtkMath::Subtract(middlePoint, firstPoint, vector1); - - for(int i = start; i < end; i+=increment){ - points->GetPoint(i, currPoint); - if(samePoint && i > start && (currPoint[0] != prevPoint[0] || currPoint[1] != prevPoint[1] || currPoint[2] != prevPoint[2])){ - samePoint = false; - } - - vtkMath::Subtract(currPoint, firstPoint, vector2); - double angle = vtkMath::AngleBetweenVectors(vector1, vector2); - if(angle > 0.0001 && collinear){ - collinear = false; - } - - centroid[0] += currPoint[0]; - centroid[1] += currPoint[1]; - centroid[2] += currPoint[2]; - std::copy(std::begin(currPoint), std::end(currPoint), prevPoint); - } - - centroid[0] /= numPoints; - centroid[1] /= numPoints; - centroid[2] /= numPoints; - - return !samePoint && !collinear; + double currPoint[3] = {}, prevPoint[3] = {}, middlePoint[3] = {}, firstPoint[3] = {}; + double vector1[3], vector2[3]; + bool samePoint = true; + int splineMidPoint = numPoints/2; + bool collinear = true; + + points->GetPoint(start, firstPoint); + points->GetPoint(splineMidPoint, middlePoint); + vtkMath::Subtract(middlePoint, firstPoint, vector1); + + for(int i = start; i < end; i+=increment){ + points->GetPoint(i, currPoint); + if(samePoint && i > start && (currPoint[0] != prevPoint[0] || currPoint[1] != prevPoint[1] || currPoint[2] != prevPoint[2])){ + samePoint = false; + } + + vtkMath::Subtract(currPoint, firstPoint, vector2); + double angle = vtkMath::AngleBetweenVectors(vector1, vector2); + if(angle > 0.0001 && collinear){ + collinear = false; + } + + centroid[0] += currPoint[0]; + centroid[1] += currPoint[1]; + centroid[2] += currPoint[2]; + std::copy(std::begin(currPoint), std::end(currPoint), prevPoint); + } + + centroid[0] /= numPoints; + centroid[1] /= numPoints; + centroid[2] /= numPoints; + + return !samePoint && !collinear; } /** -* Closes the bottom of the given countour. -* Should only be used when its an open contour. -* uPointOrder: points are ordered in U shape -*/ + * Closes the bottom of the given countour. + * Should only be used when its an open contour. + * uPointOrder: points are ordered in U shape + */ void CreateMeshFromPoints::CloseContourBottom(bool uPointOrder){ - std::vector lstIndexs = bbGetInputLstIndexs(); - int sizeLstIdexes = lstIndexs.size(); - int sizeLstX = bbGetInputLstX().size(); - - vtkSmartPointer triangleStripBottom = vtkSmartPointer::New(); - triangleStripBottom->GetPointIds()->SetNumberOfIds(sizeLstIdexes*2); - - double originPoint[3]; - points->GetPoint(0, originPoint); - int middleMeshPoint = uPointOrder?lstIndexs[0]/2:lstIndexs[0]*sizeLstIdexes/2; - - bool normalOrder = isPointingCorrectly(uPointOrder?lstIndexs[0]-1:sizeLstX-lstIndexs[0], uPointOrder?lstIndexs[0]:1, originPoint, middleMeshPoint); - - int triangleIndex = 0, currentId = 0, nextId = 0; - for(int splineIndex = 0; splineIndex < sizeLstIdexes;splineIndex++){ - nextId = uPointOrder?currentId + lstIndexs[splineIndex] - 1:sizeLstX - sizeLstIdexes + splineIndex; - if(normalOrder) - { - triangleStripBottom->GetPointIds()->SetId(triangleIndex, currentId); - triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, nextId); - } - else{ - triangleStripBottom->GetPointIds()->SetId(triangleIndex, nextId); - triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, currentId); - } - currentId = uPointOrder?nextId + 1: splineIndex+1; - triangleIndex+=2; - } - cells->InsertNextCell(triangleStripBottom); + std::vector lstIndexs = bbGetInputLstIndexs(); + int sizeLstIdexes = lstIndexs.size(); + int sizeLstX = bbGetInputLstX().size(); + + vtkSmartPointer triangleStripBottom = vtkSmartPointer::New(); + triangleStripBottom->GetPointIds()->SetNumberOfIds(sizeLstIdexes*2); + + double originPoint[3]; + points->GetPoint(0, originPoint); + int middleMeshPoint = uPointOrder?lstIndexs[0]/2:lstIndexs[0]*sizeLstIdexes/2; + + bool normalOrder = isPointingCorrectly(uPointOrder?lstIndexs[0]-1:sizeLstX-lstIndexs[0], uPointOrder?lstIndexs[0]:1, originPoint, middleMeshPoint); + + int triangleIndex = 0, currentId = 0, nextId = 0; + for(int splineIndex = 0; splineIndex < sizeLstIdexes;splineIndex++){ + nextId = uPointOrder?currentId + lstIndexs[splineIndex] - 1:sizeLstX - sizeLstIdexes + splineIndex; + if(normalOrder) + { + triangleStripBottom->GetPointIds()->SetId(triangleIndex, currentId); + triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, nextId); + } + else{ + triangleStripBottom->GetPointIds()->SetId(triangleIndex, nextId); + triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, currentId); + } + currentId = uPointOrder?nextId + 1: splineIndex+1; + triangleIndex+=2; + } + cells->InsertNextCell(triangleStripBottom); } -//===== +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) -//===== +//===== void CreateMeshFromPoints::bbUserSetDefaultValues() { - -// SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX -// Here we initialize the input 'In' to 0 -// bbSetInputIn(0); - bbSetInputCloseSurface(false); - points = NULL; - cells = NULL; - polydata = NULL; - clean = NULL; - triangle = NULL; + + // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX + // Here we initialize the input 'In' to 0 + // bbSetInputIn(0); + bbSetInputCloseSurface(false); + points = NULL; + cells = NULL; + polydata = NULL; + clean = NULL; + triangle = NULL; } -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) -//===== +//===== void CreateMeshFromPoints::bbUserInitializeProcessing() { - -// THE INITIALIZATION METHOD BODY : -// Here does nothing -// but this is where you should allocate the internal/output pointers -// if any - - + // THE INITIALIZATION METHOD BODY : + // Here does nothing + // but this is where you should allocate the internal/output pointers + // if any } -//===== + +//===== // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) -//===== +//===== void CreateMeshFromPoints::bbUserFinalizeProcessing() { - -// THE FINALIZATION METHOD BODY : -// Here does nothing -// but this is where you should desallocate the internal/output pointers -// if any - -} + + // THE FINALIZATION METHOD BODY : + // Here does nothing + // but this is where you should desallocate the internal/output pointers + // if any } -// EO namespace bbcreaVtk + +}// EO namespace bbcreaVtk diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.h b/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.h index f92f342..5a34600 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkCreateMeshFromPoints.h @@ -14,7 +14,6 @@ #include "vtkCleanPolyData.h" #include "vtkTriangleFilter.h" - namespace bbcreaVtk { diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkMarchingCubes2.h b/bbtk_creaVtk_PKG/src/bbcreaVtkMarchingCubes2.h index 21fcca2..e1f049a 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkMarchingCubes2.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkMarchingCubes2.h @@ -40,12 +40,12 @@ class bbcreaVtk_EXPORT MarchingCubes2 BBTK_BEGIN_DESCRIBE_BLACK_BOX(MarchingCubes2,bbtk::AtomicBlackBox); BBTK_NAME("MarchingCubes2"); BBTK_AUTHOR("InfoDev"); - BBTK_DESCRIPTION("No Description. (JavaScript)"); + BBTK_DESCRIPTION("(C++,JavaScript) No Description."); BBTK_CATEGORY("empty"); BBTK_INPUT(MarchingCubes2,Active,"(default true) Active",bool,""); BBTK_INPUT(MarchingCubes2,In,"Input image",vtkImageData*,""); - BBTK_INPUT(MarchingCubes2,Value,"Value of the iso-surface",double,""); + BBTK_INPUT(MarchingCubes2,Value,"(default 400) Value of the iso-surface",double,""); BBTK_INPUT(MarchingCubes2,ComputeNormalsOn,"Set the computation of normals",bool,""); BBTK_INPUT(MarchingCubes2,ComputeScalarsOn,"Set the computation of scalars",bool,""); diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataToImageData.h b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataToImageData.h index b5fd4b3..b5dc35a 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataToImageData.h +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkPolyDataToImageData.h @@ -30,7 +30,6 @@ class bbcreaVtk_EXPORT PolyDataToImageData //===== BBTK_DECLARE_INPUT(InImage,vtkImageData*); BBTK_DECLARE_INPUT(BackgroundValue,double); - BBTK_DECLARE_INPUT(InPolyData,vtkPolyData*); BBTK_DECLARE_OUTPUT(Out,vtkImageData*); BBTK_PROCESS(Process); @@ -49,7 +48,7 @@ class bbcreaVtk_EXPORT PolyDataToImageData BBTK_BEGIN_DESCRIBE_BLACK_BOX(PolyDataToImageData,bbtk::AtomicBlackBox); BBTK_NAME("PolyDataToImageData"); BBTK_AUTHOR("InfoDev"); - BBTK_DESCRIPTION("No Description."); + BBTK_DESCRIPTION("(C++, JavaScript) No Description."); BBTK_CATEGORY("empty"); BBTK_INPUT(PolyDataToImageData,InImage,"Image to put Result",vtkImageData*,""); diff --git a/bbtk_creaVtk_PKG/src/bbcreaVtkScalarsToColors.cxx b/bbtk_creaVtk_PKG/src/bbcreaVtkScalarsToColors.cxx index 4aceca3..549ce49 100644 --- a/bbtk_creaVtk_PKG/src/bbcreaVtkScalarsToColors.cxx +++ b/bbtk_creaVtk_PKG/src/bbcreaVtkScalarsToColors.cxx @@ -313,7 +313,9 @@ void ScalarsToColors::Process() double w = bbGetInputWindowColorLevel()[0] / 2; double c = bbGetInputWindowColorLevel()[1]; colorLookupTable->SetRange( c-w , c+w ); + printf("EED ScalarsToColors::Process A %f - %f\n",w, c); }else { + printf("EED ScalarsToColors::Process B\n"); colorLookupTable->SetRange(0,255); } diff --git a/lib/creaVtk/MeshFromPoints.cpp b/lib/creaVtk/MeshFromPoints.cpp new file mode 100644 index 0000000..1eaf784 --- /dev/null +++ b/lib/creaVtk/MeshFromPoints.cpp @@ -0,0 +1,456 @@ +#include "MeshFromPoints.h" + +#include "vtkTriangleStrip.h" +#include "vtkTriangle.h" +#include + +MeshFromPoints::MeshFromPoints() +{ + SetDefaultValues(); +} + +//Set Inputs +void MeshFromPoints::SetInputLstX(std::vector lst) { LstX = lst; } +void MeshFromPoints::SetInputLstY(std::vector lst) { LstY = lst; } +void MeshFromPoints::SetInputLstZ(std::vector lst) { LstZ = lst; } +void MeshFromPoints::SetInputLstIndexs(std::vector lst) { LstIndexs = lst; } +void MeshFromPoints::SetInputCloseSurface(bool value) { CloseSurface = value; } +//Get Inputs +std::vector MeshFromPoints::GetInputLstX() { return LstX; } +std::vector MeshFromPoints::GetInputLstY() { return LstY; } +std::vector MeshFromPoints::GetInputLstZ() { return LstZ; } +std::vector MeshFromPoints::GetInputLstIndexs() { return LstIndexs; } +bool MeshFromPoints::GetInputCloseSurface() { return CloseSurface; } +//Set Outputs +void MeshFromPoints::SetOutputOut(vtkPolyData* polydata) { Out = polydata; } +//Get Outputs +vtkPolyData* MeshFromPoints::GetOutputOut() { return Out; } + +void MeshFromPoints::Process() +{ + + std::vector lstX = GetInputLstX(); + std::vector lstY = GetInputLstY(); + std::vector lstZ = GetInputLstZ(); + std::vector lstIndexs = GetInputLstIndexs(); + double pointsCentroid[3]; + if ( (lstIndexs.size()<1) || (lstX.size()==0) || (lstX.size()!=lstY.size()) || (lstY.size()!=lstZ.size()) ) + { + printf("Warning! CreateMeshFromPoints::Process: List of points X Y Z and LstIndexes is not correct\n"); + SetOutputOut(NULL); + } else { + int ii,sizeSegment1,sizeSegment2; + int endSegment; + // vtkSmartPointer points = vtkSmartPointer::New(); + if (points!=NULL) points->Delete(); + points = vtkPoints::New(); + int i,sizeLstX = lstX.size(); + for (i=0;iInsertNextPoint(lstX[i],lstY[i],lstZ[i]); + pointsCentroid[0] += lstX[i]; + pointsCentroid[1] += lstY[i]; + pointsCentroid[2] += lstZ[i]; + } // for i + pointsCentroid[0] /= sizeLstX; + pointsCentroid[1] /= sizeLstX; + pointsCentroid[2] /= sizeLstX; + + if ((GetInputCloseSurface()==true) && (lstIndexs.size()>=2) ) + { + //check if initial and end points are the same in all splines (splines are in line shape and not U shape) + //to not apply changes because clean polydata will take care of it. + int count = 0; + bool differentPoints = false; + for(i=0; i < lstIndexs.size() && !differentPoints;i++){ + bool sameStart = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; + bool sameEnd = lstX[count] != lstX[count+lstIndexs[i]-1] && lstY[count] != lstY[count+lstIndexs[i]-1] && lstZ[count] != lstZ[count+lstIndexs[i]-1]; + if(!(sameStart && sameEnd)) differentPoints = true; + count += lstIndexs[i]; + } + //Correct surface normals if needed + if(differentPoints) + { + double pointSurf1[3], pointSurf2[3], pointSurf3[3]; + double vect1[3], vect2[3]; + double surfNormal[3], vectorCenter[3]; + double dotNormalSurf = 0; + for(int pIndex = 0; pIndex < lstIndexs[0]-1; pIndex++) + { + pointSurf1[0] = lstX[pIndex]; + pointSurf1[1] = lstY[pIndex]; + pointSurf1[2] = lstZ[pIndex]; + vtkMath::Subtract(pointsCentroid, pointSurf1, vectorCenter); + pointSurf2[0] = lstX[pIndex+lstIndexs[1]]; + pointSurf2[1] = lstY[pIndex+lstIndexs[1]]; + pointSurf2[2] = lstZ[pIndex+lstIndexs[1]]; + pointSurf3[0] = lstX[pIndex+1]; + pointSurf3[1] = lstY[pIndex+1]; + pointSurf3[2] = lstZ[pIndex+1]; + vtkMath::Subtract(pointSurf2, pointSurf1, vect1); + vtkMath::Subtract(pointSurf3, pointSurf1, vect2); + vtkMath::Cross(vect1, vect2, surfNormal); + dotNormalSurf += vtkMath::Dot(surfNormal, vectorCenter); + } // for pIndex + + if(dotNormalSurf > 0){ + points->Delete(); + points = vtkPoints::New(); + for(int splineI = 0; splineI < lstIndexs.size(); splineI++){ + for (i=lstIndexs[splineI]-1; i >= 0;i--) + { + points->InsertNextPoint(lstX[splineI*lstIndexs[0]+i],lstY[splineI*lstIndexs[0]+i],lstZ[splineI*lstIndexs[0]+i]); + } // for i + } // for splineI + } // if dotNormalSurf + }// if differentPoints + } + // + + // vtkSmartPointer cells = vtkSmartPointer::New(); + if (cells!=NULL) cells->Delete(); + cells = vtkCellArray::New(); + int maxElements; + int maxSegment1,maxSegment2; + int iSeg1,iSeg2; + int iGeneral = 0; + int sizeLstIdexes=lstIndexs.size(); + for (i=0; i triangleStrip = vtkSmartPointer::New(); + triangleStrip->GetPointIds()->SetNumberOfIds(sizeSegment1+sizeSegment2); + maxElements=sizeSegment1; + if (maxElementsGetPointIds()->SetId(ii*2 ,iSeg1); + triangleStrip->GetPointIds()->SetId(ii*2+1,iSeg2); + iSeg1++; + iSeg2++; + if (iSeg1>=maxSegment1) { iSeg1=maxSegment1-1; } + if (iSeg2>=maxSegment2) { iSeg2=maxSegment2-1; } + } // for ii + iGeneral=iGeneral+sizeSegment1; + cells->InsertNextCell(triangleStrip); + } //for LstIndexs + + + if(GetInputCloseSurface()) + { + int lastId1 = lstIndexs[0]-1; + int lastId2 = sizeLstX - 1; + int firstId2 = sizeLstX - lstIndexs[sizeLstIdexes - 1]; + bool face1open = std::fabs(lstX[0] - lstX[lastId1]) > 0.0001 || std::fabs(lstY[0] - lstY[lastId1]) > 0.0001 || std::fabs(lstZ[0] - lstZ[lastId1]) > 0.0001; + bool face2open = std::fabs(lstX[firstId2] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[firstId2] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[firstId2] - lstZ[lastId2]) > 0.0001; + + bool altFace1open = std::fabs(lstX[0] - lstX[firstId2]) > 0.0001 || std::fabs(lstY[0] - lstY[firstId2]) > 0.0001 || std::fabs(lstZ[0] - lstZ[firstId2]) > 0.0001; + bool altFace2open = std::fabs(lstX[lastId1] - lstX[lastId2]) > 0.0001 || std::fabs(lstY[lastId1] - lstY[lastId2]) > 0.0001 || std::fabs(lstZ[lastId1] - lstZ[lastId2]) > 0.0001; + + //false = Open Contour + //true = Closed Contour + if(!face1open && !face2open) + { + // isClosedCont = true; + CloseContourSides(lstIndexs, true, true); + } + else if(!altFace1open && !altFace2open) + { + // isClosedCont = true; + CloseContourSides(lstIndexs, false, true); + } + else{ + CloseOpenContourSurface(lstIndexs); + } + } + + // vtkPolyData *polydata = vtkPolyData::New(); + if (polydata!=NULL) polydata->Delete(); + polydata = vtkPolyData::New(); + polydata->SetPoints(points); + polydata->SetStrips(cells); + // vtkCleanPolyData *clean=vtkCleanPolyData::New(); + if (clean!=NULL) clean->Delete(); + clean = vtkCleanPolyData::New(); + clean->SetInputData(polydata); + clean->Update(); + // vtkTriangleFilter *triangle = vtkTriangleFilter::New(); + if (triangle!=NULL) triangle->Delete(); + triangle = vtkTriangleFilter::New(); + triangle->SetInputData( clean->GetOutput() ); + triangle->Update(); + SetOutputOut( triangle->GetOutput() ); + // SetOutputOut( clean->GetOutput() ); + }// if listXYZ size + //printf("PG CreateMeshFromPoints::Process: End\n"); +} + +/** + * Closes the sides of the contour + * iterates in one way or the other, depending on the order of the points and calculated vectors. + * uPointOrder: Points are order in a U shape + * lstIndexs: number of points on each spline + */ +void MeshFromPoints::CloseContourSides(std::vector lstIndexs, bool uPointOrder, bool isClosedCont){ + int sizeLstIdexes = lstIndexs.size(); + int sizePoints = GetInputLstX().size(); + + int firstIndex, end, centroidId, numPointsFace, contraryId; + int increment = uPointOrder?1:sizeLstIdexes; + double centroid[3]; + int numProcessFaces = sizeLstIdexes > 1?2:1; + for(int facesIdx = 0; facesIdx < numProcessFaces; facesIdx++){ + std::fill(std::begin(centroid), std::end(centroid), 0); + if(facesIdx == 0) + { + firstIndex = 0; + numPointsFace = uPointOrder?lstIndexs[0]: sizeLstIdexes; + end = uPointOrder?firstIndex + numPointsFace:sizePoints - lstIndexs[sizeLstIdexes - 1] + 1; + contraryId = sizePoints-1; + }else{ + firstIndex = uPointOrder?sizePoints - lstIndexs[sizeLstIdexes-1]:lstIndexs[0]-1; + numPointsFace = uPointOrder?lstIndexs[sizeLstIdexes-1]:sizeLstIdexes; + end = uPointOrder?firstIndex + numPointsFace:sizePoints; + contraryId = 0; + } + if(numPointsFace > 1) + { + bool validCentroid = CalcValidCentroid(centroid, firstIndex, end, increment, numPointsFace); + if(validCentroid) + { + bool normalOrder = isPointingCorrectly(firstIndex, firstIndex+increment, centroid, contraryId); + centroidId = points->InsertNextPoint(centroid[0], centroid[1], centroid[2]); + //vtkSmartPointer triangleStrip = vtkSmartPointer::New(); + //triangleStrip->GetPointIds()->SetNumberOfIds(numPointsFace*2 + (!isClosedCont?2:0)); + //int triangleIndex = 0; + if( normalOrder ) + { + int initial = firstIndex; + for(int index = initial; index < end; index+=increment){ + if(index+increment >= end && !isClosedCont){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, initial); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + }else if(index+increment < end){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, index+increment); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + } + /* + triangleStrip->GetPointIds()->SetId(triangleIndex,index); + triangleStrip->GetPointIds()->SetId(triangleIndex+1,centroidId);//1 + if(index+increment >= end && !isClosedCont){ + triangleStrip->GetPointIds()->SetId(triangleIndex+2,initial);//2 + triangleStrip->GetPointIds()->SetId(triangleIndex+3,centroidId);//3 + } + triangleIndex+=2; + */ + } + //cells->InsertNextCell(triangleStrip); + } else { + int initial = firstIndex-1; + int triangleStripStart = end-1; + for(int index = triangleStripStart; index > initial; index-=increment){ + if(index-increment <= initial && !isClosedCont){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, triangleStripStart); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + }else if(index-increment > initial){ + vtkNew triangle; + triangle->GetPointIds()->SetId(0, index); + triangle->GetPointIds()->SetId(1, index-increment); + triangle->GetPointIds()->SetId(2, centroidId); + cells->InsertNextCell(triangle); + } + } + }//if normalOrder + }//if validCentroid + }//if numPointsFace + }//for facesIdx + +} + +/** + * Checks if the normal from firstPointId, secPointId and centroid points away + * from the vector centroid to contrPointId. + * Used to check that the order used to create the new polygons is correct. + */ +bool MeshFromPoints::isPointingCorrectly( int firstPointId, int secPointId, double(¢roid)[3], int contrPointId) { + + double firstPoint[3], secPoint[3], contrPoint[3]; + points->GetPoint(firstPointId, firstPoint); + points->GetPoint(secPointId, secPoint); + + double firstVect[3], secVect[3], normal[3], contrVect[3]; + + vtkMath::Subtract(firstPoint, centroid, firstVect); + vtkMath::Subtract(secPoint, centroid, secVect); + + points->GetPoint(contrPointId, contrPoint); + vtkMath::Subtract(contrPoint, centroid, contrVect); + + vtkMath::Cross(firstVect, secVect, normal); + double dotCalc; + dotCalc = vtkMath::Dot(normal, contrVect); + + return dotCalc<0; +} + +/** + * Checks if the order of the points represent a curved spline (U shape) or the points resemble a straight spline. + * Now it checks the angle between each point and the vector that goes from the last point to the first. + * + * Previous version checked the curvature between 3 points in the spline, but this created problems when the straight lines + * had curves in the middle, increasing the curvature although they are not in the U shape. + */ +bool MeshFromPoints::CheckLinePointOrder(){ + int sizePoints = GetInputLstX().size(); + std::vector lstIndexs = GetInputLstIndexs(); + double point1[3], point2[3], point3[3]; + double center[3]; + double firstAngleSum = 0; + double secondAngleSum = 0; + + points->GetPoint(0, point1); + points->GetPoint((lstIndexs[0]-1), point3); + double firstVect[3]; + double secVect[3]; + vtkMath::Subtract(point3, point1, firstVect); + for(int i = 0; i < lstIndexs[0]; i++){ + points->GetPoint(i, point2); + vtkMath::Subtract(point2, point1, secVect); + firstAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); + } + points->GetPoint((sizePoints-lstIndexs[0]), point3); + vtkMath::Subtract(point3, point1, firstVect); + for(int i = 0; i < sizePoints; i+=lstIndexs.size()){ + points->GetPoint(i, point2); + vtkMath::Subtract(point2, point1, secVect); + secondAngleSum += vtkMath::SignedAngleBetweenVectors(firstVect, secVect, firstVect); + } + + return firstAngleSum < secondAngleSum; +} + +/** + * Closes an open contour + * lstIndexs: number of points on each spline + */ +void MeshFromPoints::CloseOpenContourSurface(std::vector lstIndexs){ + bool linePointOrder = CheckLinePointOrder(); + CloseContourSides(lstIndexs, !linePointOrder, false); + CloseContourBottom(!linePointOrder); +} + +/** + * Calculates centroid and checks if points are collinear. + * centroid: array to store calculation + * start: start index of points to use + * end: end index of points to use + * increment: increment to be used in point iteration + * numPoints: number of points used to calculate the centroid. + * Returns a bool indicating the validity of the centroid calculated. + * False = invalid centroid = all points are the same. + */ +bool MeshFromPoints::CalcValidCentroid(double(¢roid)[3], int start, int end, int increment, int numPoints){ + double currPoint[3] = {}, prevPoint[3] = {}, middlePoint[3] = {}, firstPoint[3] = {}; + double vector1[3], vector2[3]; + bool samePoint = true; + int splineMidPoint = numPoints/2; + bool collinear = true; + + points->GetPoint(start, firstPoint); + points->GetPoint(splineMidPoint, middlePoint); + vtkMath::Subtract(middlePoint, firstPoint, vector1); + + for(int i = start; i < end; i+=increment){ + points->GetPoint(i, currPoint); + if(samePoint && i > start && (currPoint[0] != prevPoint[0] || currPoint[1] != prevPoint[1] || currPoint[2] != prevPoint[2])){ + samePoint = false; + } + + vtkMath::Subtract(currPoint, firstPoint, vector2); + double angle = vtkMath::AngleBetweenVectors(vector1, vector2); + if(angle > 0.0001 && collinear){ + collinear = false; + } + + centroid[0] += currPoint[0]; + centroid[1] += currPoint[1]; + centroid[2] += currPoint[2]; + std::copy(std::begin(currPoint), std::end(currPoint), prevPoint); + } + + centroid[0] /= numPoints; + centroid[1] /= numPoints; + centroid[2] /= numPoints; + + return !samePoint && !collinear; +} + +/** + * Closes the bottom of the given countour. + * Should only be used when its an open contour. + * uPointOrder: points are ordered in U shape + */ +void MeshFromPoints::CloseContourBottom(bool uPointOrder){ + std::vector lstIndexs = GetInputLstIndexs(); + int sizeLstIdexes = lstIndexs.size(); + int sizeLstX = GetInputLstX().size(); + + vtkSmartPointer triangleStripBottom = vtkSmartPointer::New(); + triangleStripBottom->GetPointIds()->SetNumberOfIds(sizeLstIdexes*2); + + double originPoint[3]; + points->GetPoint(0, originPoint); + int middleMeshPoint = uPointOrder?lstIndexs[0]/2:lstIndexs[0]*sizeLstIdexes/2; + + bool normalOrder = isPointingCorrectly(uPointOrder?lstIndexs[0]-1:sizeLstX-lstIndexs[0], uPointOrder?lstIndexs[0]:1, originPoint, middleMeshPoint); + + int triangleIndex = 0, currentId = 0, nextId = 0; + for(int splineIndex = 0; splineIndex < sizeLstIdexes;splineIndex++){ + nextId = uPointOrder?currentId + lstIndexs[splineIndex] - 1:sizeLstX - sizeLstIdexes + splineIndex; + if(normalOrder) + { + triangleStripBottom->GetPointIds()->SetId(triangleIndex, currentId); + triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, nextId); + } + else{ + triangleStripBottom->GetPointIds()->SetId(triangleIndex, nextId); + triangleStripBottom->GetPointIds()->SetId(triangleIndex+1, currentId); + } + currentId = uPointOrder?nextId + 1: splineIndex+1; + triangleIndex+=2; + } + cells->InsertNextCell(triangleStripBottom); +} + +//===== +// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost) +//===== +void MeshFromPoints::SetDefaultValues() +{ + + // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX + // Here we initialize the input 'In' to 0 + // SetInputIn(0); + SetInputCloseSurface(false); + points = NULL; + cells = NULL; + polydata = NULL; + clean = NULL; + triangle = NULL; +} + + diff --git a/lib/creaVtk/MeshFromPoints.h b/lib/creaVtk/MeshFromPoints.h new file mode 100644 index 0000000..0377195 --- /dev/null +++ b/lib/creaVtk/MeshFromPoints.h @@ -0,0 +1,67 @@ + +#ifndef MeshFromPoints_h +#define MeshFromPoints_h + +//#include "creaVTK_EXPORT.h" +#include +#include +#include "vtkPoints.h" +#include "vtkCellArray.h" +#include "vtkCleanPolyData.h" +#include "vtkTriangleFilter.h" + + +class /*creaVTK_EXPORT*/ MeshFromPoints +{ +public: + MeshFromPoints(); + + //Inputs + std::vector LstX; + std::vector LstY; + std::vector LstZ; + std::vector LstIndexs; + bool CloseSurface; + //Outputs + vtkPolyData* Out; + + // Get Inputs + std::vector GetInputLstX(); + std::vector GetInputLstY(); + std::vector GetInputLstZ(); + std::vector GetInputLstIndexs(); + bool GetInputCloseSurface(); + // Set Inputs + void SetInputLstX( std::vector lst); + void SetInputLstY( std::vector lst); + void SetInputLstZ( std::vector lst); + void SetInputLstIndexs( std::vector lst); + void SetInputCloseSurface( bool value); + // Set Outputs + void SetOutputOut(vtkPolyData* polydata); + // Get Outputs + vtkPolyData* GetOutputOut(); + + // Atributes + vtkPoints *points; + vtkCellArray *cells; + vtkPolyData *polydata; + vtkCleanPolyData *clean; + vtkTriangleFilter *triangle; + + void Process(); + void SetDefaultValues(); + + // Methods + bool CalcValidCentroid(double(¢roid)[3], int start, int end, int increment, int numPoints); + bool CheckLinePointOrder(); + bool isPointingCorrectly( int firstPointId, int secPointId, double(¢roid)[3], int contrPointId); + void CloseContourBottom(bool uPointOrder); + void CloseContourSides(std::vector lstIndexs, bool uPointOrder, bool isClosedCont); + void CloseOpenContourSurface(std::vector lstIndexs); + +}; + + +#endif // _h_INCLUDED__ + diff --git a/lib/creaVtk/MeshToImageData.cpp b/lib/creaVtk/MeshToImageData.cpp new file mode 100644 index 0000000..f144a98 --- /dev/null +++ b/lib/creaVtk/MeshToImageData.cpp @@ -0,0 +1,85 @@ +#include "MeshToImageData.h" +#include + + +MeshToImageData::MeshToImageData() +{ + SetInputInPolyData(NULL); + SetInputInImage(NULL); + SetInputBackgroundValue(255); + + clean1 = NULL; + dataToStencil = NULL; + extract = NULL; + stencil = NULL; + +} + +//Set Inputs +void MeshToImageData::SetInputInImage(vtkImageData *image) { InImage = image; } +void MeshToImageData::SetInputBackgroundValue(double value) { BackgroundValue = value; } +void MeshToImageData::SetInputInPolyData(vtkPolyData *polydata) { InPolyData = polydata; } +//Get Inputs +vtkImageData *MeshToImageData::GetInputInImage() { return InImage; } +double MeshToImageData::GetInputBackgroundValue() { return BackgroundValue; } +vtkPolyData *MeshToImageData::GetInputInPolyData() { return InPolyData; } + +//Set Outputs +void MeshToImageData::SetOutputOut(vtkImageData* image) { Out = image; } +//Get Outputs +vtkImageData* MeshToImageData::GetOutputOut() { return Out; } + +void MeshToImageData::Process() +{ + if ((GetInputInPolyData()!=NULL) && (GetInputInImage()!=NULL) ) + { +printf("EED Warnning!! MeshToImageData::Process Clean this code .................\n "); + int ext[6]; + double spc[3]; + double org[3]; + GetInputInImage()->GetExtent( ext ); + GetInputInImage()->GetSpacing( spc ); + GetInputInImage()->GetOrigin( org ); + +// vtkCleanPolyData *clean1 = vtkCleanPolyData::New(); + if (clean1!=NULL) clean1->Delete(); + clean1 = vtkCleanPolyData::New(); + clean1->SetInputData( GetInputInPolyData() ); + clean1->Update(); + vtkTriangleFilter *triangle1 = vtkTriangleFilter::New(); + triangle1->SetInputData( clean1->GetOutput() ); + triangle1->Update(); +// vtkPolyDataToImageStencil *dataToStencil = vtkPolyDataToImageStencil::New(); + if (dataToStencil!=NULL) dataToStencil->Delete(); + dataToStencil = vtkPolyDataToImageStencil::New(); + dataToStencil->SetInputData( triangle1->GetOutput() ); + dataToStencil->SetOutputOrigin( org ); + dataToStencil->SetOutputSpacing( spc ); + dataToStencil->SetOutputWholeExtent( ext ); + dataToStencil->Update(); +// vtkExtractVOI *extract = vtkExtractVOI::New(); + if (extract!=NULL) extract->Delete(); + extract = vtkExtractVOI::New(); + extract->SetVOI( ext ); + extract->SetSampleRate(1, 1, 1); + extract->SetInputData( GetInputInImage() ); + extract->ReleaseDataFlagOff(); + extract->Update(); +// vtkImageStencil *stencil = vtkImageStencil::New(); + if (stencil!=NULL) stencil->Delete(); + stencil = vtkImageStencil::New(); + stencil->SetInputData( extract->GetOutput() ); + stencil->Update(); + stencil->SetStencilData( dataToStencil->GetOutput() ); + stencil->ReverseStencilOn(); + stencil->SetBackgroundValue( GetInputBackgroundValue() ); + stencil->Update(); + SetOutputOut( stencil->GetOutput() ); + } else { + printf("EED Warnning! PolyDataToImageData::Process > Missing Image or PolyData inputs\n"); + SetOutputOut( NULL); + }// if In NULL + +} + + diff --git a/lib/creaVtk/MeshToImageData.h b/lib/creaVtk/MeshToImageData.h new file mode 100644 index 0000000..b8336af --- /dev/null +++ b/lib/creaVtk/MeshToImageData.h @@ -0,0 +1,52 @@ + +#ifndef MeshToImageData_h +#define MeshToImageData_h + +//#include "creaVTK_EXPORT.h" + +#include +#include +#include +#include +#include +#include + +class /*creaVTK_EXPORT*/ MeshToImageData +{ +public: + MeshToImageData(); + //Inputs + vtkImageData *InImage; + double BackgroundValue; + vtkPolyData *InPolyData; + //Outputs + vtkImageData* Out; + + // Get Inputs + vtkImageData *GetInputInImage(); + double GetInputBackgroundValue(); + vtkPolyData *GetInputInPolyData(); + + // Set Inputs + void SetInputInImage( vtkImageData *image); + void SetInputBackgroundValue( double value ); + void SetInputInPolyData( vtkPolyData *polydata); + + // Set Outputs + void SetOutputOut(vtkImageData *image); + // Get Outputs + vtkImageData* GetOutputOut(); + + // Atributes + vtkCleanPolyData *clean1; + vtkPolyDataToImageStencil *dataToStencil; + vtkExtractVOI *extract; + vtkImageStencil *stencil; + + void Process(); + +}; + + +#endif // _h_INCLUDED__ + -- 2.50.0