/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2014 Frederik Heber. All rights reserved.
 *
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * BaseFillerPreparator.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
//#include "CodePatterns/MemDebug.hpp"
#include "BaseFillerPreparator.hpp"
#include "CodePatterns/Log.hpp"
#include "Atom/atom.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/Mesh/MeshAdaptor.hpp"
#include "Filling/Predicates/IsCloseEnoughToSurface_FillPredicate.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 "Shapes/BaseShapes.hpp"
#include "Tesselation/tesselation.hpp"
BaseFillerPreparator::BaseFillerPreparator(molecule *_filler) :
  filler(_filler),
  surface_predicate(NULL),
  LC(NULL),
  TesselStruct(NULL),
  voidnode_predicate(NULL),
  Andpredicate(NULL),
  mesh(NULL),
  inserter(NULL),
  fillerFunction(NULL)
{}
BaseFillerPreparator::~BaseFillerPreparator()
{
  // free all structures if allocated
  delete fillerFunction;
  delete inserter;
  delete mesh;
  delete Andpredicate;
  delete voidnode_predicate;
  delete TesselStruct;
  delete LC;
  delete surface_predicate;
  // given filler molecule is from someplace else
  filler = NULL;
}
void BaseFillerPreparator::addSurfacePredicate(
    const double _radius,
    std::vector &_atoms,
    const double minimum_distance)
{
  // create adaptor for the selected atoms
  PointCloudAdaptor< std::vector > cloud(&_atoms, std::string("Selected atoms"));
  // create tesselation
  LC = new LinkedCell_deprecated(cloud, 2.*_radius);
  TesselStruct = new Tesselation;
  (*TesselStruct)(cloud, _radius);
  // and create predicate
  if (minimum_distance == 0.)
	  surface_predicate =
			  new FillPredicate( IsInsideSurface_FillPredicate(
					  *TesselStruct, *LC ) );
  else
	  surface_predicate =
			  new FillPredicate( IsCloseEnoughToSurface_FillPredicate(
					  *TesselStruct, *LC, minimum_distance ) );
}
void BaseFillerPreparator::addRandomInserter(
    const double _RandAtomDisplacement,
    const double _RandMoleculeDisplacement,
    const bool _DoRotate)
{
  inserter = new Inserter(
      Inserter::impl_ptr(
          new RandomInserter(
              _RandAtomDisplacement,
              _RandMoleculeDisplacement,
              _DoRotate)
          )
      );
}
void BaseFillerPreparator::addVoidPredicate(
    const double _mindistance)
{
  voidnode_predicate = new FillPredicate(
      IsVoidNode_FillPredicate(
          Sphere(zeroVec, _mindistance)
          )
      );
}
bool BaseFillerPreparator::operator()()
{
  if ((mesh != NULL)
      && (inserter != NULL)
      && (voidnode_predicate != NULL)) {
    FillPredicate Andpredicate = *voidnode_predicate;
    if (surface_predicate != NULL)
      Andpredicate = (Andpredicate) && !(*surface_predicate);
    fillerFunction = new Filler(*mesh, Andpredicate, *inserter);
    return true;
  } else {
    return false;
  }
}