/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2012 University of Bonn. 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 .
 */
/*
 * IsVoidNode_FillPredicate.cpp
 *
 *  Created on: Jan 16, 2012
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include 
#include "IsVoidNode_FillPredicate.hpp"
#include "CodePatterns/Log.hpp"
#include "Atom/TesselPoint.hpp"
#include "LinkedCell/LinkedCell_View.hpp"
#include "Shapes/ShapeOps.hpp"
#include "Tesselation/tesselation.hpp"
#include "World.hpp"
#include "AnyFillPredicate.hpp"
#include "FillPredicate.hpp"
/** Checks whether a given node \a n in the domain is empty with respect to the
 * given \a shape.
 *
 * @param LC View of a linked cell structure for finding neighbors quickly
 * @param shape shape as a sort of placeholder
 * @param n point where to center the placeholder
 * @return true - placeholder at node contains no points,
 *         false - there is at least one point contained
 */
bool IsVoidNode(const LinkedCell::LinkedCell_View &LC, const Shape &shape, const Node &n)
{
  LOG(3, "DEBUG: Node is " << n << ".");
  LOG(3, "DEBUG: Original shape is at " << shape.getCenter() << " with radius of "
      << shape.getRadius() << ".");
  const Shape shapeAtn = translate(shape, n);
  LOG(3, "DEBUG: Translated shape is at " << shapeAtn.getCenter() << ".");
  LinkedCell::LinkedList neighborlist = LC.getAllNeighbors(
      shapeAtn.getRadius(), shapeAtn.getCenter());
  LOG(3, "DEBUG: we have " << neighborlist.size() << " possible neighbors.");
  LinkedCell::LinkedList::const_iterator neighboriter =
      std::find_if(neighborlist.begin(), neighborlist.end(),
          boost::bind(&Shape::isInside, shapeAtn,
              boost::bind(&TesselPoint::getPosition, _1) ));
  return neighboriter == neighborlist.end();
}
FillPredicate IsVoidNode_FillPredicate(const Shape &_shape)
{
  // copy _shape !
  const LinkedCell::LinkedCell_View LC = World::getInstance().getLinkedCell(_shape.getRadius());
  AnyFillPredicate::FillPredicator function = boost::bind(&IsVoidNode, LC, _shape, _1);
  LOG(2, "DEBUG: Create IsVoidNode_FillPredicate from shape at "
      << _shape.getCenter() << " and radius " << _shape.getRadius() << ".");
  FillPredicate::impl_ptr impl(new AnyFillPredicate(function));
  return FillPredicate(impl);
}