/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * ShapeOps.cpp * * Created on: Jun 18, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "Shapes/ShapeExceptions.hpp" #include "Shapes/ShapeOps.hpp" #include "Shapes/ShapeOps_impl.hpp" #include "LinearAlgebra/Vector.hpp" #include "CodePatterns/Assert.hpp" /*************** Base case ***********************/ ShapeOpsBase_impl::ShapeOpsBase_impl(const Shape::impl_ptr &_arg) : arg(_arg){} ShapeOpsBase_impl::~ShapeOpsBase_impl(){} bool ShapeOpsBase_impl::isInside(const Vector &point){ return arg->isInside(translateIn(point)); } bool ShapeOpsBase_impl::isOnSurface(const Vector &point){ return arg->isOnSurface(translateIn(point)); } Vector ShapeOpsBase_impl::getNormal(const Vector &point) throw (NotOnSurfaceException){ Vector helper = translateIn(point); if(!arg->isOnSurface(helper)){ throw NotOnSurfaceException() << ShapeVector(&helper); } Vector res = translateOutNormal(arg->getNormal(helper)); res.Normalize(); return res; } LineSegmentSet ShapeOpsBase_impl::getLineIntersections(const Line &line){ Line newLine(translateIn(line.getOrigin()),translateIn(line.getDirection())); LineSegmentSet res(line); LineSegmentSet helper = getArg()->getLineIntersections(newLine); for(LineSegmentSet::iterator iter = helper.begin();iter!=helper.end();++iter){ LinePoint lpBegin = iter->getBegin(); LinePoint lpEnd = iter->getBegin(); // translate both linepoints lpBegin = lpBegin.isNegInfinity()? line.negEndpoint(): line.getLinePoint(translateOutPos(lpBegin.getPoint())); lpEnd = lpEnd.isPosInfinity()? line.posEndpoint(): line.getLinePoint(translateOutPos(lpEnd.getPoint())); res.insert(LineSegment(lpBegin,lpEnd)); } return res; } std::vector ShapeOpsBase_impl::getHomogeneousPointsOnSurface(const size_t N) const { return getArg()->getHomogeneousPointsOnSurface(N);; } Shape::impl_ptr ShapeOpsBase_impl::getArg() const{ return arg; } /********************* Resize ********************/ Resize_impl::Resize_impl(const Shape::impl_ptr &_arg,double _size) : ShapeOpsBase_impl(_arg), size(_size) { ASSERT(size>0,"Cannot resize a Shape to size zero or below"); } Resize_impl::~Resize_impl(){} bool Resize_impl::isInside(const Vector& point){ return getArg()->isInside((1/size) * point); } Vector Resize_impl::translateIn(const Vector& point){ return (1/size) * point; } Vector Resize_impl::translateOutPos(const Vector& point){ return size * point; } Vector Resize_impl::translateOutNormal(const Vector& point){ return point; } string Resize_impl::toString(){ stringstream sstr; sstr << "resize(" << getArg()->toString() << "," << size << ")"; return sstr.str(); } std::vector Resize_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface = getArg()->getHomogeneousPointsOnSurface(N); for(std::vector::iterator iter = PointsOnSurface.begin(); iter != PointsOnSurface.end(); ++iter) { *iter *= size; } return PointsOnSurface; } Shape resize(const Shape &arg,double size){ Shape::impl_ptr impl = Shape::impl_ptr(new Resize_impl(getShapeImpl(arg),size)); return Shape(impl); } /*************************** translate *******************/ Translate_impl::Translate_impl(const Shape::impl_ptr &_arg, const Vector &_offset) : ShapeOpsBase_impl(_arg),offset(_offset) {} Translate_impl::~Translate_impl(){} bool Translate_impl::isInside(const Vector& point){ return getArg()->isInside(point-offset); } Vector Translate_impl::translateIn(const Vector& point){ return point-offset; } Vector Translate_impl::translateOutPos(const Vector& point){ return point+offset; } Vector Translate_impl::translateOutNormal(const Vector& point){ return point; } string Translate_impl::toString(){ stringstream sstr; sstr << "translate(" << getArg()->toString() << "," << offset << ")"; return sstr.str(); } std::vector Translate_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface = getArg()->getHomogeneousPointsOnSurface(N); for(std::vector::iterator iter = PointsOnSurface.begin(); iter != PointsOnSurface.end(); ++iter) { *iter += offset; } return PointsOnSurface; } Shape translate(const Shape &arg, const Vector &offset){ Shape::impl_ptr impl = Shape::impl_ptr(new Translate_impl(getShapeImpl(arg),offset)); return Shape(impl); } /*********************** stretch ******************/ Stretch_impl::Stretch_impl(const Shape::impl_ptr &_arg, const Vector &_factors) : ShapeOpsBase_impl(_arg),factors(_factors) { ASSERT(factors[0]>0,"cannot stretch a shape by a negative amount"); ASSERT(factors[1]>0,"cannot stretch a shape by a negative amount"); ASSERT(factors[2]>0,"cannot stretch a shape by a negative amount"); for(int i = NDIM;i--;){ reciFactors[i] = 1/factors[i]; } } Stretch_impl::~Stretch_impl(){} bool Stretch_impl::isInside(const Vector& point){ Vector helper=point; helper.ScaleAll(reciFactors); return getArg()->isInside(helper); } Vector Stretch_impl::translateIn(const Vector& point){ Vector helper=point; helper.ScaleAll(reciFactors); return helper; } Vector Stretch_impl::translateOutPos(const Vector& point){ Vector helper=point; helper.ScaleAll(factors); return helper; } Vector Stretch_impl::translateOutNormal(const Vector& point){ Vector helper=point; // the normalFactors are derived from appearances of the factors // with in the vectorproduct Vector normalFactors; normalFactors[0]=factors[1]*factors[2]; normalFactors[1]=factors[0]*factors[2]; normalFactors[2]=factors[0]*factors[1]; helper.ScaleAll(normalFactors); return helper; } string Stretch_impl::toString(){ stringstream sstr; sstr << "stretch(" << getArg()->toString() << "," << factors << ")"; return sstr.str(); } std::vector Stretch_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface = getArg()->getHomogeneousPointsOnSurface(N); for(std::vector::iterator iter = PointsOnSurface.begin(); iter != PointsOnSurface.end(); ++iter) { (*iter).ScaleAll(reciFactors); } return PointsOnSurface; } Shape stretch(const Shape &arg, const Vector &factors){ Shape::impl_ptr impl = Shape::impl_ptr(new Stretch_impl(getShapeImpl(arg),factors)); return Shape(impl); } /************************* transform *****************/ Transform_impl::Transform_impl(const Shape::impl_ptr &_arg, const RealSpaceMatrix &_transformation) : ShapeOpsBase_impl(_arg),transformation(_transformation) { transformationInv = transformation.invert(); } Transform_impl::~Transform_impl(){} bool Transform_impl::isInside(const Vector& point){ return getArg()->isInside(transformationInv * point); } Vector Transform_impl::translateIn(const Vector& point){ return transformationInv * point; } Vector Transform_impl::translateOutPos(const Vector& point){ return transformation * point; } Vector Transform_impl::translateOutNormal(const Vector& point){ RealSpaceMatrix mat = transformation.invert().transpose(); return mat * point; } string Transform_impl::toString(){ stringstream sstr; sstr << "transform(" << getArg()->toString() << "," << transformation << ")"; return sstr.str(); } std::vector Transform_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface = getArg()->getHomogeneousPointsOnSurface(N); for(std::vector::iterator iter = PointsOnSurface.begin(); iter != PointsOnSurface.end(); ++iter) { *iter = transformation * (*iter); } return PointsOnSurface; } Shape transform(const Shape &arg, const RealSpaceMatrix &transformation){ Shape::impl_ptr impl = Shape::impl_ptr(new Transform_impl(getShapeImpl(arg),transformation)); return Shape(impl); }