From 9f0583a0be7a9754f08e3e17746b024417f7b09b Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Sat, 26 Jan 2013 18:19:44 +0100 Subject: [PATCH] changes to computeDual functions --- Apps/Examples/volumeExplorer.cpp | 2 +- include/Algo/Modelisation/subdivision.h | 23 ++- include/Algo/Modelisation/subdivision.hpp | 168 +++++++++++++++++- include/Algo/Modelisation/subdivision3.h | 10 +- include/Algo/Modelisation/subdivision3.hpp | 96 ++--------- include/Geometry/inclusion.h | 1 + include/Topology/gmap/gmap2.h | 13 +- include/Topology/gmap/gmap3.h | 13 ++ include/Topology/map/map3.h | 1 - include/Utils/convertType.h | 1 + src/Topology/gmap/gmap2.cpp | 16 ++ src/Topology/gmap/gmap3.cpp | 20 +++ src/Topology/map/map3.cpp | 191 +++++++++++++-------- 13 files changed, 391 insertions(+), 164 deletions(-) diff --git a/Apps/Examples/volumeExplorer.cpp b/Apps/Examples/volumeExplorer.cpp index af7fff39..db871a9e 100644 --- a/Apps/Examples/volumeExplorer.cpp +++ b/Apps/Examples/volumeExplorer.cpp @@ -200,7 +200,7 @@ void MyQT::cb_initGL() // create the renders m_topo_render = new Algo::Render::GL2::Topo3Render(); - m_explode_render = new Algo::Render::GL2::ExplodeVolumeRender(true,true); + m_explode_render = new Algo::Render::GL2::ExplodeVolumeRender(true,true,true); SelectorDartNoBoundary nb(myMap); m_topo_render->updateData(myMap, position, 0.8f, 0.8f, 0.8f, nb); diff --git a/include/Algo/Modelisation/subdivision.h b/include/Algo/Modelisation/subdivision.h index 4dfff725..7aa2005d 100644 --- a/include/Algo/Modelisation/subdivision.h +++ b/include/Algo/Modelisation/subdivision.h @@ -115,16 +115,35 @@ void TwoNPlusOneSubdivision(typename PFP::MAP& map, EMBV& attributs, const Funct template void DooSabin(typename PFP::MAP& map, VertexAttribute& position); -//** +///** +// * Reverse the orientation of the map +// * NOW IN THE MAP // */ //template //void Sqrt3Subdivision(typename PFP::MAP& map, typename PFP::TVEC3& position, const FunctorSelect& selected = allDarts) ; +///** +// * Sqrt(3) subdivision scheme +// */ +//template +//void Sqrt3Subdivision(typename PFP::MAP& map, typename PFP::TVEC3& position, const FunctorSelect& selected = allDarts) ; + +template +void computeDual(typename PFP::MAP& map, VertexAttribute& position); + +template +void computeBoundaryConstraintDual(typename PFP::MAP& map, VertexAttribute& position); + +template +void computeBoundaryConstraintKeepingOldVerticesDual(typename PFP::MAP& map, VertexAttribute& position); + + + } // namespace Modelisation -} +} // namespace Surface } // namespace Algo diff --git a/include/Algo/Modelisation/subdivision.hpp b/include/Algo/Modelisation/subdivision.hpp index 2011c3af..d607d704 100644 --- a/include/Algo/Modelisation/subdivision.hpp +++ b/include/Algo/Modelisation/subdivision.hpp @@ -628,7 +628,6 @@ void DooSabin(typename PFP::MAP& map, VertexAttribute& posit } } - inline double sqrt3_K(unsigned int n) { switch(n) @@ -698,11 +697,176 @@ inline double sqrt3_K(unsigned int n) // } //} +template +void computeDual(typename PFP::MAP& map, VertexAttribute& position) +{ + // Face Attribute -> after dual new Vertex Attribute + FaceAttribute positionF = map.template getAttribute("position") ; + if(!positionF.isValid()) + positionF = map.template addAttribute("position") ; -} // namespace Modelisation + // Compute Centroid for the faces + Algo::Surface::Geometry::computeCentroidFaces(map, position, positionF) ; + + // Compute the Dual mesh + map.computeDual(); + position = positionF ; +} + + +template +void computeBoundaryConstraintDual(typename PFP::MAP& map, VertexAttribute& position) +{ + // Face Attribute -> after dual new Vertex Attribute + FaceAttribute positionF = map.template getAttribute("position") ; + if(!positionF.isValid()) + positionF = map.template addAttribute("position") ; + + //Triangule boundary faces & compute for each new face the centroid + std::vector boundsDart; + DartMarkerStore mf(map); + for(Dart dit = map.begin() ; dit != map.end() ; map.next(dit)) + { + if(!mf.isMarked(dit) && map.isBoundaryMarked2(dit)) + { + boundsDart.push_back(dit); + Dart db = dit; + Dart d1 = map.phi1(db); + Dart dprev = map.phi_1(db); + map.splitFace(db, d1) ; + map.cutEdge(map.phi_1(db)) ; + + positionF[dit] = (position[dit] + position[map.phi2(dit)]) * typename PFP::REAL(0.5); + mf.markOrbit(dit); + + Dart x = map.phi2(map.phi_1(db)) ; + Dart dd = map.phi1(map.phi1(map.phi1(x))); + while(dd != x) + { + Dart next = map.phi1(dd) ; + Dart prev = map.phi_1(dd); + map.splitFace(dd, map.phi1(x)) ; + positionF[prev] = (position[prev] + position[map.phi1(prev)]) * typename PFP::REAL(0.5); + mf.markOrbit(prev); + dd = next ; + } + + positionF[dprev] = (position[dprev] + position[map.phi1(dprev)]) * typename PFP::REAL(0.5); + mf.markOrbit(dprev); + } + } + + // Compute Centroid for the other faces + Algo::Surface::Geometry::computeCentroidFaces(map, position, positionF) ; + + // Fill the holes + for(Dart dit = map.begin() ; dit != map.end() ; map.next(dit)) + { + if(mf.isMarked(dit) && map.isBoundaryMarked2(dit)) + { + map.fillHole(dit); + mf.unmarkOrbit(dit); + } + } + + // Compute the Dual mesh + map.computeDual(); + position = positionF ; + + // Create the new border with the old boundary edges + for(std::vector::iterator it = boundsDart.begin() ; it != boundsDart.end() ; ++it) + { + map.createHole(map.phi2(map.phi1(*it))); + } +} +template +void computeBoundaryConstraintKeepingOldVerticesDual(typename PFP::MAP& map, VertexAttribute& position) +{ + // Face Attribute -> after dual new Vertex Attribute + FaceAttribute positionF = map.template getAttribute("position") ; + if(!positionF.isValid()) + positionF = map.template addAttribute("position") ; + + //Triangule boundary faces & compute for each new face the centroid + std::vector boundsDart; + DartMarkerStore mf(map); + for(Dart dit = map.begin() ; dit != map.end() ; map.next(dit)) + { + if(!mf.isMarked(dit) && map.isBoundaryMarked2(dit)) + { + boundsDart.push_back(dit); + Dart db = dit; + Dart d1 = map.phi1(db); + Dart dprev = map.phi_1(db); + map.splitFace(db, d1) ; + map.cutEdge(map.phi_1(db)) ; + + positionF[dit] = (position[dit] + position[map.phi2(dit)]) * typename PFP::REAL(0.5); + mf.markOrbit(dit); + + Dart x = map.phi2(map.phi_1(db)) ; + Dart dd = map.phi1(map.phi1(map.phi1(x))); + while(dd != x) + { + Dart next = map.phi1(dd) ; + Dart prev = map.phi_1(dd); + map.splitFace(dd, map.phi1(x)) ; + positionF[prev] = (position[prev] + position[map.phi1(prev)]) * typename PFP::REAL(0.5); + mf.markOrbit(prev); + dd = next ; + } + + positionF[dprev] = (position[dprev] + position[map.phi1(dprev)]) * typename PFP::REAL(0.5); + mf.markOrbit(dprev); + } + } + + // Compute Centroid for the other faces + Algo::Surface::Geometry::computeCentroidFaces(map, position, positionF) ; + + // Fill the holes + for(Dart dit = map.begin() ; dit != map.end() ; map.next(dit)) + { + if(mf.isMarked(dit) && map.isBoundaryMarked2(dit)) + { + map.fillHole(dit); + mf.unmarkOrbit(dit); + } + } + + // Compute the Dual mesh + map.computeDual(); + + //Saving old position VertexAttribute to a FaceAttribute + FaceAttribute temp; + temp = position; + position = positionF ; + positionF = temp; + + // Create the new border with the old boundary edges + for(std::vector::iterator it = boundsDart.begin() ; it != boundsDart.end() ; ++it) + { + map.createHole(map.phi2(map.phi1(*it))); + } + + // Manage old vertices with new FaceAttribute + for(Dart dit = map.begin() ; dit != map.end() ; map.next(dit)) + { + if(!mf.isMarked(dit) && map.isBoundaryMarked2(dit)) + { + Dart nd = map.cutEdge(dit); + position[nd] = positionF[map.phi2(dit)]; + mf.markOrbit(dit); + mf.markOrbit(nd); + } + } } +} // namespace Modelisation + +} // namespace Surface + } // namespace Algo } // namespace CGoGN diff --git a/include/Algo/Modelisation/subdivision3.h b/include/Algo/Modelisation/subdivision3.h index 38f1460d..0a55c465 100644 --- a/include/Algo/Modelisation/subdivision3.h +++ b/include/Algo/Modelisation/subdivision3.h @@ -102,15 +102,13 @@ void catmullClarkVol(typename PFP::MAP& map, VertexAttribute template void sqrt3Vol(typename PFP::MAP& map, VertexAttribute& position, const FunctorSelect& selected = allDarts); -///** -// * Dual mesh computation -// */ -//template -//void computeDual3(typename PFP::MAP& map, const FunctorSelect& selected = allDarts) ; +template +void computeDual(typename PFP::MAP& map, VertexAttribute& position); + } // namespace Modelisation -} +} // namespace Volume } // namespace Algo diff --git a/include/Algo/Modelisation/subdivision3.hpp b/include/Algo/Modelisation/subdivision3.hpp index 513a651a..8939a52f 100644 --- a/include/Algo/Modelisation/subdivision3.hpp +++ b/include/Algo/Modelisation/subdivision3.hpp @@ -716,87 +716,21 @@ void sqrt3Vol(typename PFP::MAP& map, VertexAttribute& posit } } -//template -//void reverseOrientation3(typename PFP::MAP& map) -//{ -// DartAttribute emb0(&map, map.template getEmbeddingAttributeVector()) ; -// if(emb0.isValid()) -// { -// DartAttribute new_emb0 = map.template addAttribute("new_EMB_0") ; -// for(Dart d = map.begin(); d != map.end(); map.next(d)) -// new_emb0[d] = emb0[map.phi1(d)] ; -// map.template swapAttributes(emb0, new_emb0) ; -// map.removeAttribute(new_emb0) ; -// } -// -// DartAttribute phi2 = map.template getAttribute("phi2") ; -// DartAttribute phi3 = map.template getAttribute("phi3") ; -// map.template swapAttributes(phi2, phi3) ; -//} -// -//template -//void computeDual3(typename PFP::MAP& map, const FunctorSelect& selected) -//{ -// DartAttribute phi1 = map.template getAttribute("phi1") ; -// DartAttribute phi_1 = map.template getAttribute("phi_1") ; -// DartAttribute new_phi1 = map.template addAttribute("new_phi1") ; -// DartAttribute new_phi_1 = map.template addAttribute("new_phi_1") ; -// -// DartAttribute phi2 = map.template getAttribute("phi2") ; -// DartAttribute new_phi2 = map.template addAttribute("new_phi2") ; -// -// for(Dart d = map.begin(); d != map.end(); map.next(d)) -// { -// Dart dd = map.phi2(map.phi3(d)) ; -// new_phi1[d] = dd ; -// new_phi_1[dd] = d ; -// -// Dart ddd = map.phi1(map.phi3(d)); -// new_phi2[d] = ddd; -// new_phi2[ddd] = d; -// } -// -// map.template swapAttributes(phi1, new_phi1) ; -// map.template swapAttributes(phi_1, new_phi_1) ; -// map.template swapAttributes(phi2, new_phi2) ; -// -// map.removeAttribute(new_phi1) ; -// map.removeAttribute(new_phi_1) ; -// map.removeAttribute(new_phi2) ; -// -// map.swapEmbeddingContainers(VERTEX, VOLUME) ; -// -// for(Dart d = map.begin(); d != map.end(); map.next(d)) -// { -// if(map.isBoundaryMarked(d)) -// { -// map.deleteVolume(d); -//// Traversor3VW tWV(map, d); -//// std::vector v; -//// for(Dart ditW = tWV.begin() ; ditW != tWV.end() ; ditW = tWV.next()) -//// { -//// v.push_back(ditW); -//// } -//// -//// for(std::vector::iterator it = v.begin() ; it != v.end() ; ++it) -//// { -//// map.deleteVolume(*it); -//// } -// -// } -// } -// -//// reverseOrientation3(map) ; -// -// //boundary management -//// for(Dart d = map.begin(); d != map.end(); map.next(d)) -//// { -//// if(map.isBoundaryMarked(d)) -//// { -//// map.deleteVolume(d); //map.template boundaryMarkOrbit( -//// } -//// } -//} +template +void computeDual(typename PFP::MAP& map, VertexAttribute& position) +{ + // VolumeAttribute -> after dual new VertexAttribute + VolumeAttribute positionV = map.template getAttribute("position") ; + if(!positionV.isValid()) + positionV = map.template addAttribute("position") ; + + // Compute Centroid for the volumes + Algo::Volume::Geometry::computeCentroidVolumes(map, position, positionV) ; + + // Compute the Dual mesh + map.computeDual(); + position = positionV ; +} } //namespace Modelisation diff --git a/include/Geometry/inclusion.h b/include/Geometry/inclusion.h index 870c30a3..982a568d 100644 --- a/include/Geometry/inclusion.h +++ b/include/Geometry/inclusion.h @@ -25,6 +25,7 @@ #ifndef __INCLUSION__ #define __INCLUSION__ + #include "Geometry/basic.h" #include "Geometry/orientation.h" diff --git a/include/Topology/gmap/gmap2.h b/include/Topology/gmap/gmap2.h index 40007201..d33f278d 100644 --- a/include/Topology/gmap/gmap2.h +++ b/include/Topology/gmap/gmap2.h @@ -439,8 +439,6 @@ public: * @param fonct functor obj ref */ bool foreach_dart_of_edge1(Dart d, FunctorType& fonct, unsigned int thread = 0); - - //@} /*! @name Close map after import or creation @@ -469,6 +467,17 @@ public: */ unsigned int closeMap(); //@} + + /*! @name Compute dual + * These functions compute the dual mesh + *************************************************************************/ + + //@{ + //! Dual mesh computation + /*! + */ + void computeDual(); + //@} }; } // namespace CGoGN diff --git a/include/Topology/gmap/gmap3.h b/include/Topology/gmap/gmap3.h index 379c085c..de29fab1 100644 --- a/include/Topology/gmap/gmap3.h +++ b/include/Topology/gmap/gmap3.h @@ -378,6 +378,19 @@ public: * @return the number of closed holes */ unsigned int closeMap(); + //@} + + /*! @name Compute dual + * These functions compute the dual mesh + *************************************************************************/ + + //@{ + //! Dual mesh computation + /*! + */ + void computeDual(); + //@} + }; } // namespace CGoGN diff --git a/include/Topology/map/map3.h b/include/Topology/map/map3.h index d03aba56..a23a699b 100644 --- a/include/Topology/map/map3.h +++ b/include/Topology/map/map3.h @@ -432,7 +432,6 @@ public: * These functions must be used with care, generally only by import algorithms *************************************************************************/ - //@{ /** * create a face of map1 marked as boundary diff --git a/include/Utils/convertType.h b/include/Utils/convertType.h index 4f2e3a82..7d00a455 100644 --- a/include/Utils/convertType.h +++ b/include/Utils/convertType.h @@ -27,6 +27,7 @@ #include #include +#include namespace CGoGN { diff --git a/src/Topology/gmap/gmap2.cpp b/src/Topology/gmap/gmap2.cpp index 119a9b32..132d9c0a 100644 --- a/src/Topology/gmap/gmap2.cpp +++ b/src/Topology/gmap/gmap2.cpp @@ -947,4 +947,20 @@ unsigned int GMap2::closeMap() return nb ; } +/*! @name Compute dual + * These functions compute the dual mesh + *************************************************************************/ + +void GMap2::computeDual() +{ +// DartAttribute old_beta0 = this->getAttribute("beta0"); +// DartAttribute old_beta2 = this->getAttribute("beta2") ; +// +// swapAttributes(old_beta0, old_beta2) ; +// +// swapEmbeddingContainers(VERTEX, FACE) ; +// +// //boundary management ? +} + } // namespace CGoGN diff --git a/src/Topology/gmap/gmap3.cpp b/src/Topology/gmap/gmap3.cpp index aa456173..f90f03dc 100644 --- a/src/Topology/gmap/gmap3.cpp +++ b/src/Topology/gmap/gmap3.cpp @@ -996,4 +996,24 @@ unsigned int GMap3::closeMap() return nb ; } +/*! @name Compute dual + * These functions compute the dual mesh + *************************************************************************/ + +void GMap3::computeDual() +{ +// DartAttribute old_beta0 = getAttribute("beta0"); +// DartAttribute old_beta1 = getAttribute("beta1"); +// DartAttribute old_beta2 = getAttribute("beta2"); +// DartAttribute old_beta3 = getAttribute("beta3") ; +// +// swapAttributes(old_beta0, old_beta3) ; +// swapAttributes(old_beta1, old_beta2) ; +// +// swapEmbeddingContainers(VERTEX, FACE) ; +// +// //boundary management ? +} + + } // namespace CGoGN diff --git a/src/Topology/map/map3.cpp b/src/Topology/map/map3.cpp index c9c13515..aa624dbb 100644 --- a/src/Topology/map/map3.cpp +++ b/src/Topology/map/map3.cpp @@ -278,8 +278,8 @@ Dart Map3::splitVertex(std::vector& vd) Dart Map3::deleteVertex(Dart d) { - if(isBoundaryVertex(d)) - return NIL ; + //if(isBoundaryVertex(d)) + // return NIL ; // Save the darts around the vertex // (one dart per face should be enough) @@ -301,27 +301,55 @@ Dart Map3::deleteVertex(Dart d) } } + std::cout << "nb faces " << fstore.size() << std::endl; + Dart res = NIL ; for(std::vector::iterator it = fstore.begin() ; it != fstore.end() ; ++it) { Dart fit = *it ; Dart end = phi_1(fit) ; fit = phi1(fit) ; - while(fit != end) + + if(fit == end) { - Dart d2 = phi2(fit) ; - Dart d3 = phi3(fit) ; - Dart d32 = phi2(d3) ; + std::cout << " mmmmmmmmmmmmmmmmmmmmmerrrrrrrrrrrrrrrrrde !!!!!!!!!!!! " << std::endl; - if(res == NIL) - res = d2 ; +// Dart d2 = phi2(fit) ; +// Dart d23 = phi3(d2) ; +// Dart d3 = phi3(fit) ; +// Dart d32 = phi2(d3) ; +// +// //phi3unsew() +// phi3sew(d3,23); +// +// fit = phi_1(fit); +// +// d2 = phi2(fit) ; +// d23 = phi3(d2) ; +// d3 = phi3(fit) ; +// d32 = phi2(d3) ; +// phi3sew(d3,23); - phi2unsew(d2) ; - phi2unsew(d32) ; - phi2sew(d2, d32) ; - phi2sew(fit, d3) ; +// Map2::deleteCC(fit); + } + else + { + while(fit != end) + { + Dart d2 = phi2(fit) ; + Dart d3 = phi3(fit) ; + Dart d32 = phi2(d3) ; - fit = phi1(fit) ; + if(res == NIL) + res = d2 ; + + phi2unsew(d2) ; + phi2unsew(d32) ; + phi2sew(d2, d32) ; + phi2sew(fit, d3) ; + + fit = phi1(fit) ; + } } } @@ -1270,60 +1298,86 @@ void Map3::computeDual() unsigned int count = 0; - for(Dart d = begin(); d != end(); next(d)) - { - if(isBoundaryMarked3(d)) - boundaryUnmark<3>(d); - - - if(d == 1569) - { - std::cout << "d " << std::endl; - - Traversor3WE t(*this,d); - for(Dart dit = t.begin() ; dit != t.end() ; dit = t.next()) - { - Dart temp = dit; - do - { - if(isBoundaryMarked3(d)) - std::cout << "d boundary " << std::endl; - - temp = alpha2(temp); - }while(temp != dit); - } - - if(isBoundaryMarked3(d)) - std::cout << "d boundary " << std::endl; - - if(isBoundaryMarked3(phi1(d))) - std::cout << "phi1(d) boundary " << std::endl; - - if(isBoundaryMarked3(phi_1(d))) - std::cout << "phi_1(d) boundary " << std::endl; - - if(isBoundaryMarked3(phi2(d))) - std::cout << "phi2(d) boundary " << std::endl; - - if(isBoundaryMarked3(phi3(d))) - std::cout << "phi3(d) boundary " << std::endl; - - if(isBoundaryMarked3(phi2(phi3(d)))) - std::cout << "phi2(phi3(d)) boundary " << std::endl; - - if(isBoundaryMarked3(phi3(phi2(d)))) - std::cout << "phi3(phi2(d)) boundary " << std::endl; - - if(isBoundaryMarked3(phi1(phi3(d)))) - std::cout << "phi1(phi3(d)) boundary " << std::endl; - - if(isBoundaryMarked3(phi3(phi1(d)))) - std::cout << "phi3(phi1(d)) boundary " << std::endl; - } - - if(isBoundaryMarked3(d)) - { + std::vector vbound; +// for(Dart d = begin(); d != end(); next(d)) +// { +// if(isBoundaryMarked3(d) && !isBoundaryMarked3(phi3(d))) +// { +// vbound.push_back(d); +// } +// } +// +// std::cout << "vbound size = " << vbound.size() << std::endl; +// +// for(std::vector::iterator it = vbound.begin() ; it != vbound.end() ; ++it) +// { +// Dart d = *it; +// //Dart d3 = phi3(d); +// phi3unsew(d); +// //phi3unsew(d3); +// } +// +// //std::cout << "nb faces : " << closeMap() << std::endl; +// +// if(d == 14208) +// { +// std::cout << "yeahhhhhhhh" << std::endl; +// std::cout << "isBoundaryMarked ? " << isBoundaryMarked3(phi3(phi2(14208))) << std::endl; +// +// } +// +// //boundaryUnmark<3>(d); +// +// } +// if(d == 1569) +// { +// std::cout << "d " << std::endl; +// +// Traversor3WE t(*this,d); +// for(Dart dit = t.begin() ; dit != t.end() ; dit = t.next()) +// { +// Dart temp = dit; +// do +// { +// if(isBoundaryMarked3(d)) +// std::cout << "d boundary " << std::endl; +// +// temp = alpha2(temp); +// }while(temp != dit); +// } +// +// if(isBoundaryMarked3(d)) +// std::cout << "d boundary " << std::endl; +// +// if(isBoundaryMarked3(phi1(d))) +// std::cout << "phi1(d) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi_1(d))) +// std::cout << "phi_1(d) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi2(d))) +// std::cout << "phi2(d) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi3(d))) +// std::cout << "phi3(d) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi2(phi3(d)))) +// std::cout << "phi2(phi3(d)) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi3(phi2(d)))) +// std::cout << "phi3(phi2(d)) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi1(phi3(d)))) +// std::cout << "phi1(phi3(d)) boundary " << std::endl; +// +// if(isBoundaryMarked3(phi3(phi1(d)))) +// std::cout << "phi3(phi1(d)) boundary " << std::endl; +// } +// +// if(isBoundaryMarked3(d)) +// { +// // if(isBoundaryMarked3(d)) // std::cout << "d = " << d << std::endl; // @@ -1342,8 +1396,8 @@ void Map3::computeDual() // // if(count == 5) // return; - } - } +// } +// } // TraversorW tW(*this); @@ -1414,7 +1468,6 @@ void Map3::computeDualTest() new_phi1[d] = dd ; new_phi_1[dd] = d ; - //Dart ddd = phi3(phi_1(d)); Dart ddd = phi1(phi3(d)); new_phi2[d] = ddd; new_phi2[ddd] = d; -- GitLab