From 67381b22b0a3db04085b1e686d90f0bdf1aa068e Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Feb 2019 13:58:00 +0100 Subject: [PATCH 1/6] Support triangulation in VTK_io_plugin --- .../demo/Polyhedron/Plugins/IO/CMakeLists.txt | 2 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 113 +++++++++++++++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index 4a642daba09..1db22a9c7a4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -35,7 +35,7 @@ if (VTK_FOUND) if ("${VTK_VERSION_MAJOR}" GREATER "5") if(VTK_LIBRARIES) polyhedron_demo_plugin(vtk_plugin VTK_io_plugin KEYWORDS IO Mesh_3) - target_link_libraries(vtk_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_c3t3_item + target_link_libraries(vtk_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_c3t3_item scene_points_with_normal_item vtkCommonCore vtkIOCore vtkIOLegacy vtkIOXML vtkFiltersCore vtkFiltersSources) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index c5cbd68a15e..769b51cb5c8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -20,10 +20,11 @@ // #include -#include "Scene_c3t3_item.h" #include #include "Scene_surface_mesh_item.h" +#include "Scene_c3t3_item.h" +#include "Scene_points_with_normal_item.h" #include "Scene_polylines_item.h" #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -422,12 +424,119 @@ public: msgBox.exec(); } - if (CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) + if (extension!="vtu" && CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) { Scene_facegraph_item* poly_item = new Scene_facegraph_item(poly); poly_item->setName(fileinfo.fileName()); return poly_item; } + else if (extension=="vtu") + { + vtkUnstructuredGrid* data_vtu = vtkUnstructuredGrid::SafeDownCast(data); + bool all_tri(true); + + for(int i = 0; i< data_vtu->GetNumberOfCells(); ++i) + { + if(data_vtu->GetCellType(i) != 5) + all_tri = false; + } + + if(all_tri && CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) + { + Scene_facegraph_item* poly_item = new Scene_facegraph_item(poly); + poly_item->setName(fileinfo.fileName()); + return poly_item; + } + typedef boost::array Facet; // 3 = id + typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference + Scene_c3t3_item* c3t3_item = new Scene_c3t3_item(); + c3t3_item->set_valid(false); + //build a triangulation from data: + std::vector points; + vtkPoints* dataP = data_vtu->GetPoints();; + for(int i = 0; i< data_vtu->GetNumberOfPoints(); ++i) + { + double *p = dataP->GetPoint(i); + points.push_back(Tr::Point(p[0],p[1],p[2])); + } + std::vector finite_cells; + bool has_mesh_domain = data_vtu->GetCellData()->HasArray("MeshDomain"); + vtkDataArray* domains = data_vtu->GetCellData()->GetArray("MeshDomain"); + for(int i = 0; i< data_vtu->GetNumberOfCells(); ++i) + { + if(data_vtu->GetCellType(i) != 10 ) + continue; + vtkIdList* pids = data_vtu->GetCell(i)->GetPointIds(); + Tet_with_ref cell; + for(int j = 0; j<4; ++j) + cell[j] = pids->GetId(j); + cell[4] = has_mesh_domain ? static_cast(domains->GetComponent(i,0)) + :1; + finite_cells.push_back(cell); + } + std::map border_facets; + if(finite_cells.empty())//then there is no triangles either, only display points + { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(CGAL::Three::Three::mainWindow(), "No cells", + "This file does not hold" + " a 3D triangulation nore " + "a polygon mesh. Displaying points only."); + Scene_points_with_normal_item* pi = new Scene_points_with_normal_item(); + BOOST_FOREACH(const Tr::Point& p, points) + { + pi->point_set()->insert(Point_3(p.x(), p.y(), p.z())); + } + pi->setName(QString("%1_points").arg(fileinfo.baseName())); + delete c3t3_item; + return pi; + + } + CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); + + for( C3t3::Triangulation::Finite_cells_iterator + cit = c3t3_item->c3t3().triangulation().finite_cells_begin(); + cit != c3t3_item->c3t3().triangulation().finite_cells_end(); + ++cit) + { + CGAL_assertion(cit->info() >= 0); + c3t3_item->c3t3().add_to_complex(cit, cit->info()); + for(int i=0; i < 4; ++i) + { + if(cit->surface_patch_index(i)>0) + { + c3t3_item->c3t3().add_to_complex(cit, i, cit->surface_patch_index(i)); + } + } + } + + //if there is no facet in the complex, we add the border facets. + if(c3t3_item->c3t3().number_of_facets_in_complex() == 0) + { + for( C3t3::Triangulation::Finite_facets_iterator + fit = c3t3_item->c3t3().triangulation().finite_facets_begin(); + fit != c3t3_item->c3t3().triangulation().finite_facets_end(); + ++fit) + { + typedef C3t3::Triangulation::Cell_handle Cell_handle; + + Cell_handle c = fit->first; + Cell_handle nc = c->neighbor(fit->second); + + // By definition, Subdomain_index() is supposed to be the id of the exterior + if(c->subdomain_index() != C3t3::Triangulation::Cell::Subdomain_index() && + nc->subdomain_index() == C3t3::Triangulation::Cell::Subdomain_index()) + { + // Color the border facet with the index of its cell + c3t3_item->c3t3().add_to_complex(c, fit->second, c->subdomain_index()); + } + } + } + c3t3_item->c3t3_changed(); + c3t3_item->resetCutPlane(); + c3t3_item->setName(fileinfo.baseName()); + return c3t3_item; + } else{ // extract only segments std::vector< std::vector > segments; From 7056e8099be01a1df785b5044f5e5fdb5a454ab9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Feb 2019 14:39:22 +0100 Subject: [PATCH 2/6] WIP --- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 769b51cb5c8..30dfb372c2f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -24,8 +24,8 @@ #include "Scene_surface_mesh_item.h" #include "Scene_c3t3_item.h" -#include "Scene_points_with_normal_item.h" #include "Scene_polylines_item.h" +#include "Scene_points_with_normal_item.h" #include #include @@ -154,6 +154,8 @@ namespace CGAL{ //extract cells for (vtkIdType i = 0; iGetCellType(i) == 10)//skip tetrahedra + continue; vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); @@ -191,7 +193,7 @@ namespace CGAL{ vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); - if (nb_vertices !=2) continue; + if (nb_vertices !=2) continue ; segments.push_back( std::vector() ); segments.back().push_back(point_map[cell_ptr->GetPointId(0)]); segments.back().push_back(point_map[cell_ptr->GetPointId(1)]); @@ -357,10 +359,12 @@ public: { CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_facegraph_item* item = - new Scene_facegraph_item(poly); + new Scene_facegraph_item(); item->setName(fileinfo.completeBaseName()); return item; } + + vtkSmartPointer data; vtkSmartPointer obs = vtkSmartPointer::New(); @@ -432,12 +436,11 @@ public: } else if (extension=="vtu") { - vtkUnstructuredGrid* data_vtu = vtkUnstructuredGrid::SafeDownCast(data); bool all_tri(true); - for(int i = 0; i< data_vtu->GetNumberOfCells(); ++i) + for(int i = 0; i< data->GetNumberOfCells(); ++i) { - if(data_vtu->GetCellType(i) != 5) + if(data->GetCellType(i) != 5) all_tri = false; } @@ -453,20 +456,20 @@ public: c3t3_item->set_valid(false); //build a triangulation from data: std::vector points; - vtkPoints* dataP = data_vtu->GetPoints();; - for(int i = 0; i< data_vtu->GetNumberOfPoints(); ++i) + vtkPoints* dataP = data->GetPoints();; + for(int i = 0; i< data->GetNumberOfPoints(); ++i) { double *p = dataP->GetPoint(i); points.push_back(Tr::Point(p[0],p[1],p[2])); } std::vector finite_cells; - bool has_mesh_domain = data_vtu->GetCellData()->HasArray("MeshDomain"); - vtkDataArray* domains = data_vtu->GetCellData()->GetArray("MeshDomain"); - for(int i = 0; i< data_vtu->GetNumberOfCells(); ++i) + bool has_mesh_domain = data->GetCellData()->HasArray("MeshDomain"); + vtkDataArray* domains = data->GetCellData()->GetArray("MeshDomain"); + for(int i = 0; i< data->GetNumberOfCells(); ++i) { - if(data_vtu->GetCellType(i) != 10 ) + if(data->GetCellType(i) != 10 ) continue; - vtkIdList* pids = data_vtu->GetCell(i)->GetPointIds(); + vtkIdList* pids = data->GetCell(i)->GetPointIds(); Tet_with_ref cell; for(int j = 0; j<4; ++j) cell[j] = pids->GetId(j); @@ -474,24 +477,13 @@ public: :1; finite_cells.push_back(cell); } - std::map border_facets; - if(finite_cells.empty())//then there is no triangles either, only display points + //if no finite_cell, then only display edges : go to end of function + if(finite_cells.empty()) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(CGAL::Three::Three::mainWindow(), "No cells", - "This file does not hold" - " a 3D triangulation nore " - "a polygon mesh. Displaying points only."); - Scene_points_with_normal_item* pi = new Scene_points_with_normal_item(); - BOOST_FOREACH(const Tr::Point& p, points) - { - pi->point_set()->insert(Point_3(p.x(), p.y(), p.z())); - } - pi->setName(QString("%1_points").arg(fileinfo.baseName())); delete c3t3_item; - return pi; - + goto polylines_only; } + std::map border_facets; CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); for( C3t3::Triangulation::Finite_cells_iterator @@ -537,18 +529,35 @@ public: c3t3_item->setName(fileinfo.baseName()); return c3t3_item; } - else{ - // extract only segments - std::vector< std::vector > segments; - extract_segments_from_vtkPointSet(data,segments); - if (segments.empty()) return NULL; /// TODO handle point sets +polylines_only: // if no other cell type was found + // extract only segments + std::vector< std::vector > segments; + extract_segments_from_vtkPointSet(data,segments); + if (segments.empty()) return NULL; /// TODO handle point sets + if(!segments.empty()) + { Scene_polylines_item* polyline_item = new Scene_polylines_item(); - polyline_item->setName(fileinfo.fileName()); BOOST_FOREACH(const std::vector& segment, segments) - polyline_item->polylines.push_back(segment); + polyline_item->polylines.push_back(segment); + polyline_item->setName(fileinfo.fileName()); return polyline_item; } - return NULL; + + //if nothing else worked, display at least the points + QApplication::restoreOverrideCursor(); + QMessageBox::warning(CGAL::Three::Three::mainWindow(), + "Problematic file", + "This program does probably not support the type of cell" + "of this file. Only points will be displayed."); + QApplication::setOverrideCursor(Qt::WaitCursor); + Scene_points_with_normal_item* point_item = new Scene_points_with_normal_item(); + for(int i=0; i< data->GetNumberOfPoints(); ++i) + { + double* p = data->GetPoint(i); + point_item->point_set()->insert(Point_3(p[0], p[1], p[2])); + } + point_item->setName(fileinfo.baseName()); + return point_item; } }; // end Polyhedron_demo_vtk_plugin From 257311b0dedab73875ae3889a6aae3e82c3237e6 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Feb 2019 15:23:30 +0100 Subject: [PATCH 3/6] rework vtk_io_plugin --- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 118 +++++++++++------- 1 file changed, 76 insertions(+), 42 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 30dfb372c2f..9f8f46d3592 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -154,7 +154,9 @@ namespace CGAL{ //extract cells for (vtkIdType i = 0; iGetCellType(i) == 10)//skip tetrahedra + if(poly_data->GetCellType(i) != 5 + && poly_data->GetCellType(i) != 7 + && poly_data->GetCellType(i) != 9) //only supported cells are triangles, quads and polygons continue; vtkCell* cell_ptr = poly_data->GetCell(i); @@ -190,13 +192,17 @@ namespace CGAL{ //extract segments for (vtkIdType i = 0; iGetCellType(i) != 3 + && poly_data->GetCellType(i) != 4) + continue; vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); - if (nb_vertices !=2) continue ; segments.push_back( std::vector() ); - segments.back().push_back(point_map[cell_ptr->GetPointId(0)]); - segments.back().push_back(point_map[cell_ptr->GetPointId(1)]); + for(int j = 0; j < nb_vertices; ++j) + { + segments.back().push_back(point_map[cell_ptr->GetPointId(j)]); + } } } @@ -352,9 +358,7 @@ public: std::string fname = fileinfo.absoluteFilePath().toStdString(); - FaceGraph* poly = new FaceGraph(); // Try to read .vtk in a facegraph - if(fileinfo.size() == 0) { CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); @@ -364,7 +368,6 @@ public: return item; } - vtkSmartPointer data; vtkSmartPointer obs = vtkSmartPointer::New(); @@ -428,28 +431,50 @@ public: msgBox.exec(); } - if (extension!="vtu" && CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) + //check celltypes + bool is_polygon_mesh(false), + is_c3t3(false), + is_polyline(false); + for(int i = 0; i< data->GetNumberOfCells(); ++i) { - Scene_facegraph_item* poly_item = new Scene_facegraph_item(poly); - poly_item->setName(fileinfo.fileName()); - return poly_item; + int t = data->GetCellType(i); + if( t == 5 || t == 7 || t == 9) //tri, quad or polygon + is_polygon_mesh = true; + else if(t == 10) //tetrahedron + is_c3t3 = true; + else if( t == 3 || t == 4) //line or polyline + is_polyline = true; } - else if (extension=="vtu") + Scene_group_item* group = nullptr; + if((is_polygon_mesh && is_c3t3) + || (is_polygon_mesh && is_polyline) + || (is_c3t3 && is_polyline) ) { - bool all_tri(true); - - for(int i = 0; i< data->GetNumberOfCells(); ++i) - { - if(data->GetCellType(i) != 5) - all_tri = false; - } - - if(all_tri && CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) + group = new Scene_group_item(fileinfo.baseName()); + group->setScene(CGAL::Three::Three::scene()); + } + + if(is_polygon_mesh) + { + FaceGraph* poly = new FaceGraph(); + if (CGAL::vtkPointSet_to_polygon_mesh(data, *poly)) { Scene_facegraph_item* poly_item = new Scene_facegraph_item(poly); - poly_item->setName(fileinfo.fileName()); - return poly_item; + if(group) + { + poly_item->setName(QString("%1_faces").arg(fileinfo.baseName())); + CGAL::Three::Three::scene()->addItem(poly_item); + CGAL::Three::Three::scene()->changeGroup(poly_item, group); + } + else{ + poly_item->setName(fileinfo.baseName()); + return poly_item; + } } + } + + if (is_c3t3) + { typedef boost::array Facet; // 3 = id typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference Scene_c3t3_item* c3t3_item = new Scene_c3t3_item(); @@ -477,12 +502,6 @@ public: :1; finite_cells.push_back(cell); } - //if no finite_cell, then only display edges : go to end of function - if(finite_cells.empty()) - { - delete c3t3_item; - goto polylines_only; - } std::map border_facets; CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); @@ -526,29 +545,44 @@ public: } c3t3_item->c3t3_changed(); c3t3_item->resetCutPlane(); - c3t3_item->setName(fileinfo.baseName()); - return c3t3_item; + if(group) + { + c3t3_item->setName(QString("%1_tetrahedra").arg(fileinfo.baseName())); + CGAL::Three::Three::scene()->addItem(c3t3_item); + CGAL::Three::Three::scene()->changeGroup(c3t3_item, group); + } + else{ + c3t3_item->setName(fileinfo.baseName()); + return c3t3_item; + } } -polylines_only: // if no other cell type was found - // extract only segments - std::vector< std::vector > segments; - extract_segments_from_vtkPointSet(data,segments); - if (segments.empty()) return NULL; /// TODO handle point sets - if(!segments.empty()) + + if(is_polyline) { + std::vector< std::vector > segments; + extract_segments_from_vtkPointSet(data,segments); Scene_polylines_item* polyline_item = new Scene_polylines_item(); BOOST_FOREACH(const std::vector& segment, segments) polyline_item->polylines.push_back(segment); - polyline_item->setName(fileinfo.fileName()); - return polyline_item; + if(group) + { + polyline_item->setName(QString("%1_lines").arg(fileinfo.baseName())); + CGAL::Three::Three::scene()->addItem(polyline_item); + CGAL::Three::Three::scene()->changeGroup(polyline_item, group); + } + else{ + polyline_item->setName(fileinfo.baseName()); + return polyline_item; + } } - //if nothing else worked, display at least the points + if(group) + return group; + QApplication::restoreOverrideCursor(); QMessageBox::warning(CGAL::Three::Three::mainWindow(), "Problematic file", - "This program does probably not support the type of cell" - "of this file. Only points will be displayed."); + "Cell type not recognized. Only points will be displayed."); QApplication::setOverrideCursor(Qt::WaitCursor); Scene_points_with_normal_item* point_item = new Scene_points_with_normal_item(); for(int i=0; i< data->GetNumberOfPoints(); ++i) From 535acc73a269a0520decdd17b3460d43815f4307 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 7 Feb 2019 12:10:57 +0100 Subject: [PATCH 4/6] Add preprocessing for build_triangulation --- .../demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 9f8f46d3592..3f742211534 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -503,6 +503,22 @@ public: finite_cells.push_back(cell); } std::map border_facets; + //Preprocessing for build_triangulation + //check for orientation and swap in cells if not good. + for(std::size_t i=0; i(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); for( C3t3::Triangulation::Finite_cells_iterator From d8ac1ce7611be920b4b48597e3d6b18a2ffbc7c6 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 7 Feb 2019 14:04:53 +0100 Subject: [PATCH 5/6] Fix children management in reload group. --- Polyhedron/demo/Polyhedron/Scene.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 38956320395..15a935b7e85 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -98,16 +98,15 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi this, SLOT(callDraw())); CGAL::Three::Scene_group_item* group = qobject_cast(m_entries[index]); + QList group_children; if(group) { - QList group_children; Q_FOREACH(Item_id id, group->getChildren()) { CGAL::Three::Scene_item* child = group->getChild(id); group->unlockChild(child); - group_children << item_id(child); + group_children << child; } - erase(group_children); } CGAL::Three::Scene_group_item* parent = m_entries[index]->parentGroup(); bool is_locked = false; @@ -148,6 +147,10 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi Q_EMIT restoreCollapsedState(); redraw_model(); Q_EMIT selectionChanged(index); + Q_FOREACH(Scene_item* child, group_children) + { + erase(item_id(child)); + } return item; } From 6a93f23208266deb98529fb1d3d5e3ef8999d91a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 7 Feb 2019 14:15:53 +0100 Subject: [PATCH 6/6] Fix case where required renderingmdoe is unsupported. Won't infinit loop anymore. --- Polyhedron/demo/Polyhedron/Scene.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 15a935b7e85..7994c82d144 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -1016,10 +1016,13 @@ Scene::setData(const QModelIndex &index, { RenderingMode rendering_mode = static_cast(value.toInt()); // Find next supported rendering mode + int counter = 0; while ( ! item->supportsRenderingMode(rendering_mode) ) { rendering_mode = static_cast( (rendering_mode+1) % NumberOfRenderingMode ); + if(counter++ == NumberOfRenderingMode) + break; } item->setRenderingMode(rendering_mode); QModelIndex nindex = createIndex(m_entries.size()-1,RenderingModeColumn+1);