/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * FillRegularGridAction.cpp * * Created on: Jan 12, 2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "Actions/UndoRedoHelpers.hpp" #include "Atom/atom.hpp" #include "Atom/AtomicInfo.hpp" #include "Atom/CopyAtoms/CopyAtoms_withBonds.hpp" #include "Bond/BondInfo.hpp" #include "CodePatterns/Log.hpp" #include "Descriptors/MoleculeOrderDescriptor.hpp" #include "Filling/Cluster.hpp" #include "Filling/Filler.hpp" #include "Filling/Inserter/Inserter.hpp" #include "Filling/Inserter/RandomInserter.hpp" #include "Filling/Mesh/CubeMesh.hpp" #include "Filling/Predicates/IsInsideSurface_FillPredicate.hpp" #include "Filling/Predicates/IsVoidNode_FillPredicate.hpp" #include "Filling/Predicates/Ops_FillPredicate.hpp" #include "LinkedCell/linkedcell.hpp" #include "LinkedCell/PointCloudAdaptor.hpp" #include "molecule.hpp" #include "MoleculeListClass.hpp" #include "Parser/FormatParserInterface.hpp" #include "Parser/FormatParserStorage.hpp" #include "Shapes/BaseShapes.hpp" #include "Tesselation/tesselation.hpp" #include "Tesselation/BoundaryLineSet.hpp" #include "Tesselation/BoundaryTriangleSet.hpp" #include "Tesselation/CandidateForTesselation.hpp" #include "World.hpp" #include #include #include #include #include "Actions/FillAction/FillRegularGridAction.hpp" using namespace MoleCuilder; // and construct the stuff #include "FillRegularGridAction.def" #include "Action_impl_pre.hpp" /** =========== define the function ====================== */ Action::state_ptr FillRegularGridAction::performCall() { typedef std::vector AtomVector; // get the filler molecule std::vector movedatoms; const std::vector< molecule *> molecules = World::getInstance().getSelectedMolecules(); if (molecules.size() != 1) { ELOG(1, "No exactly one molecule selected, aborting,"); return Action::failure; } molecule *filler = *(molecules.begin()); for(molecule::const_iterator iter = filler->begin(); iter != filler->end(); ++iter) movedatoms.push_back( AtomicInfo(*(*iter)) ); LOG(1, "INFO: Chosen molecule has " << filler->size() << " atoms."); // check for selected molecules and create surfaces from them std::vector atoms(World::getInstance().getSelectedAtoms()); FillPredicate * surface_predicate = NULL; LinkedCell_deprecated * LC = NULL; Tesselation * TesselStruct = NULL; if (params.SphereRadius != 0.) { if ( atoms.size() == 0) { ELOG(1, "You have given a sphere radius " << params.SphereRadius << " != 0, but have not select any molecules."); return Action::failure; } // create adaptor for the selected atoms PointCloudAdaptor< std::vector > cloud(&atoms, std::string("Selected atoms")); // create tesselation LC = new LinkedCell_deprecated(cloud, 2.*params.SphereRadius); TesselStruct = new Tesselation; (*TesselStruct)(cloud, params.SphereRadius); // and create predicate surface_predicate = new FillPredicate( IsInsideSurface_FillPredicate( *TesselStruct, *LC ) ); } // create predicate, mesh, and filler FillRegularGridState *UndoState = NULL; bool successflag = false; { FillPredicate *voidnode_predicate = new FillPredicate( IsVoidNode_FillPredicate( Sphere(zeroVec, params.mindistance) ) ); FillPredicate Andpredicate = (*voidnode_predicate); if (surface_predicate != NULL) Andpredicate = (Andpredicate) && !(*surface_predicate); Mesh *mesh = new CubeMesh(params.counts, params.offset, World::getInstance().getDomain().getM()); Inserter *inserter = new Inserter( Inserter::impl_ptr( new RandomInserter( params.RandAtomDisplacement, params.RandMoleculeDisplacement, params.DoRotate) ) ); // fill { Filler *fillerFunction = new Filler(*mesh, Andpredicate, *inserter); ClusterInterface::Cluster_impl cluster( new Cluster( filler->getAtomIds(), filler->getBoundingShape()) ); CopyAtoms_withBonds copyMethod; Filler::ClusterVector_t ClonedClusters; successflag = (*fillerFunction)(copyMethod, cluster, ClonedClusters); delete fillerFunction; // append each cluster's atoms to clonedatoms (however not selected ones) std::vector clonedatoms; std::vector clonedatominfos; for (Filler::ClusterVector_t::const_iterator iter = ClonedClusters.begin(); iter != ClonedClusters.end(); ++iter) { const AtomIdSet &atoms = (*iter)->getAtomIds(); clonedatoms.reserve(clonedatoms.size()+atoms.size()); for (AtomIdSet::const_iterator atomiter = atoms.begin(); atomiter != atoms.end(); ++atomiter) if (!filler->containsAtom(*atomiter)) { clonedatoms.push_back( *atomiter ); clonedatominfos.push_back( AtomicInfo(*(*atomiter)) ); } } std::vector< BondInfo > clonedbonds; StoreBondInformationFromAtoms(clonedatoms, clonedbonds); LOG(2, "DEBUG: There are " << clonedatominfos.size() << " newly created atoms."); if (!successflag) { ELOG(1, "Insertion failed, removing inserted clusters, translating original one back"); RemoveAtomsFromAtomicInfo(clonedatominfos); clonedatoms.clear(); SetAtomsFromAtomicInfo(movedatoms); } else { std::vector MovedToVector(filler->size(), zeroVec); std::transform(filler->begin(), filler->end(), MovedToVector.begin(), boost::bind(&AtomInfo::getPosition, _1) ); UndoState = new FillRegularGridState(clonedatominfos,clonedbonds,movedatoms,MovedToVector,params); } } // remove delete mesh; delete inserter; delete voidnode_predicate; delete surface_predicate; delete LC; delete TesselStruct; } if (successflag) return Action::state_ptr(UndoState); else return Action::failure; } Action::state_ptr FillRegularGridAction::performUndo(Action::state_ptr _state) { FillRegularGridState *state = assert_cast(_state.get()); // remove all created atoms RemoveAtomsFromAtomicInfo(state->clonedatoms); // add the original cluster SetAtomsFromAtomicInfo(state->movedatoms); return Action::state_ptr(_state); } Action::state_ptr FillRegularGridAction::performRedo(Action::state_ptr _state){ FillRegularGridState *state = assert_cast(_state.get()); // place filler cluster again at new spot ResetAtomPosition(state->movedatoms, state->MovedToVector); // re-create all clusters bool statusflag = AddAtomsFromAtomicInfo(state->clonedatoms); // re-create the bonds if (statusflag) AddBondsFromBondInfo(state->clonedbonds); if (statusflag) return Action::state_ptr(_state); else return Action::failure; } bool FillRegularGridAction::canUndo() { return true; } bool FillRegularGridAction::shouldUndo() { return true; } /** =========== end of function ====================== */