[bcf653] | 1 | /*
|
---|
| 2 | * Project: MoleCuilder
|
---|
| 3 | * Description: creates and alters molecular systems
|
---|
[0aa122] | 4 | * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
|
---|
[5aaa43] | 5 | * Copyright (C) 2013 Frederik Heber. All rights reserved.
|
---|
[94d5ac6] | 6 | *
|
---|
| 7 | *
|
---|
| 8 | * This file is part of MoleCuilder.
|
---|
| 9 | *
|
---|
| 10 | * MoleCuilder is free software: you can redistribute it and/or modify
|
---|
| 11 | * it under the terms of the GNU General Public License as published by
|
---|
| 12 | * the Free Software Foundation, either version 2 of the License, or
|
---|
| 13 | * (at your option) any later version.
|
---|
| 14 | *
|
---|
| 15 | * MoleCuilder is distributed in the hope that it will be useful,
|
---|
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 18 | * GNU General Public License for more details.
|
---|
| 19 | *
|
---|
| 20 | * You should have received a copy of the GNU General Public License
|
---|
| 21 | * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
|
---|
[bcf653] | 22 | */
|
---|
| 23 |
|
---|
[e09b70] | 24 | /*
|
---|
| 25 | * ShapeOps.cpp
|
---|
| 26 | *
|
---|
| 27 | * Created on: Jun 18, 2010
|
---|
| 28 | * Author: crueger
|
---|
| 29 | */
|
---|
| 30 |
|
---|
[bf3817] | 31 | // include config.h
|
---|
| 32 | #ifdef HAVE_CONFIG_H
|
---|
| 33 | #include <config.h>
|
---|
| 34 | #endif
|
---|
| 35 |
|
---|
[ad011c] | 36 | #include "CodePatterns/MemDebug.hpp"
|
---|
[bbbad5] | 37 |
|
---|
[5a8d61] | 38 | #include <algorithm>
|
---|
| 39 | #include <boost/bind.hpp>
|
---|
[08a09ed] | 40 | #include <cmath>
|
---|
[5a8d61] | 41 |
|
---|
[b94634] | 42 | #include "Shapes/ShapeExceptions.hpp"
|
---|
[e09b70] | 43 | #include "Shapes/ShapeOps.hpp"
|
---|
| 44 | #include "Shapes/ShapeOps_impl.hpp"
|
---|
| 45 |
|
---|
[6c438f] | 46 | #include "LinearAlgebra/Vector.hpp"
|
---|
[ad011c] | 47 | #include "CodePatterns/Assert.hpp"
|
---|
[394529] | 48 |
|
---|
[5de9da] | 49 | /*************** Base case ***********************/
|
---|
| 50 |
|
---|
| 51 | ShapeOpsBase_impl::ShapeOpsBase_impl(const Shape::impl_ptr &_arg) :
|
---|
| 52 | arg(_arg){}
|
---|
| 53 |
|
---|
| 54 | ShapeOpsBase_impl::~ShapeOpsBase_impl(){}
|
---|
| 55 |
|
---|
[735940] | 56 | bool ShapeOpsBase_impl::isInside(const Vector &point) const{
|
---|
[5de9da] | 57 | return arg->isInside(translateIn(point));
|
---|
| 58 | }
|
---|
| 59 |
|
---|
[735940] | 60 | bool ShapeOpsBase_impl::isOnSurface(const Vector &point) const{
|
---|
[5de9da] | 61 | return arg->isOnSurface(translateIn(point));
|
---|
| 62 | }
|
---|
| 63 |
|
---|
[735940] | 64 | Vector ShapeOpsBase_impl::getNormal(const Vector &point) const throw (NotOnSurfaceException){
|
---|
[5de9da] | 65 | Vector helper = translateIn(point);
|
---|
| 66 | if(!arg->isOnSurface(helper)){
|
---|
[b94634] | 67 | throw NotOnSurfaceException() << ShapeVector(&helper);
|
---|
[5de9da] | 68 | }
|
---|
[f12805] | 69 | Vector res = translateOutNormal(arg->getNormal(helper));
|
---|
| 70 | res.Normalize();
|
---|
| 71 | return res;
|
---|
[5de9da] | 72 | }
|
---|
| 73 |
|
---|
[6acc2f3] | 74 | Vector ShapeOpsBase_impl::getCenter() const
|
---|
| 75 | {
|
---|
| 76 | return arg->getCenter();
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | double ShapeOpsBase_impl::getRadius() const
|
---|
| 80 | {
|
---|
| 81 | return translateOutPos(Vector(arg->getRadius(), 0., 0.)).Norm();
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 |
|
---|
[735940] | 85 | LineSegmentSet ShapeOpsBase_impl::getLineIntersections(const Line &line) const{
|
---|
[c6f395] | 86 | Line newLine(translateIn(line.getOrigin()),translateIn(line.getDirection()));
|
---|
| 87 | LineSegmentSet res(line);
|
---|
| 88 | LineSegmentSet helper = getArg()->getLineIntersections(newLine);
|
---|
| 89 | for(LineSegmentSet::iterator iter = helper.begin();iter!=helper.end();++iter){
|
---|
| 90 | LinePoint lpBegin = iter->getBegin();
|
---|
| 91 | LinePoint lpEnd = iter->getBegin();
|
---|
| 92 | // translate both linepoints
|
---|
| 93 | lpBegin = lpBegin.isNegInfinity()?
|
---|
| 94 | line.negEndpoint():
|
---|
| 95 | line.getLinePoint(translateOutPos(lpBegin.getPoint()));
|
---|
| 96 | lpEnd = lpEnd.isPosInfinity()?
|
---|
| 97 | line.posEndpoint():
|
---|
| 98 | line.getLinePoint(translateOutPos(lpEnd.getPoint()));
|
---|
| 99 | res.insert(LineSegment(lpBegin,lpEnd));
|
---|
| 100 | }
|
---|
| 101 | return res;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
[b92e4a] | 104 | enum ShapeType ShapeOpsBase_impl::getType() const {
|
---|
| 105 | return getArg()->getType();
|
---|
| 106 | }
|
---|
| 107 |
|
---|
[6c438f] | 108 | std::vector<Vector> ShapeOpsBase_impl::getHomogeneousPointsOnSurface(const size_t N) const {
|
---|
[c48641] | 109 | std::vector<Vector> PointsOnSurface = getArg()->getHomogeneousPointsOnSurface(N);
|
---|
| 110 | std::transform(PointsOnSurface.begin(), PointsOnSurface.end(), PointsOnSurface.begin(),
|
---|
| 111 | boost::bind(&ShapeOpsBase_impl::translateOutPos, this, _1) );
|
---|
| 112 | return PointsOnSurface;
|
---|
[5a8d61] | 113 | }
|
---|
| 114 |
|
---|
| 115 | std::vector<Vector> ShapeOpsBase_impl::getHomogeneousPointsInVolume(const size_t N) const {
|
---|
[c48641] | 116 | std::vector<Vector> PointsOnSurface = getArg()->getHomogeneousPointsInVolume(N);
|
---|
| 117 | std::transform(PointsOnSurface.begin(), PointsOnSurface.end(), PointsOnSurface.begin(),
|
---|
| 118 | boost::bind(&ShapeOpsBase_impl::translateOutPos, this, _1) );
|
---|
| 119 | return PointsOnSurface;
|
---|
[6c438f] | 120 | }
|
---|
| 121 |
|
---|
| 122 | Shape::impl_ptr ShapeOpsBase_impl::getArg() const{
|
---|
[cfda65] | 123 | return arg;
|
---|
| 124 | }
|
---|
| 125 |
|
---|
[5e588b5] | 126 | /********************* Resize ********************/
|
---|
| 127 |
|
---|
[e09b70] | 128 | Resize_impl::Resize_impl(const Shape::impl_ptr &_arg,double _size) :
|
---|
[5de9da] | 129 | ShapeOpsBase_impl(_arg), size(_size)
|
---|
[394529] | 130 | {
|
---|
| 131 | ASSERT(size>0,"Cannot resize a Shape to size zero or below");
|
---|
| 132 | }
|
---|
[e09b70] | 133 |
|
---|
| 134 | Resize_impl::~Resize_impl(){}
|
---|
| 135 |
|
---|
[c67c65] | 136 | double Resize_impl::getVolume() const
|
---|
| 137 | {
|
---|
[b98a32] | 138 | return getArg()->getVolume() * size * size * size;
|
---|
[c67c65] | 139 | }
|
---|
| 140 |
|
---|
| 141 | double Resize_impl::getSurfaceArea() const
|
---|
| 142 | {
|
---|
[b98a32] | 143 | return getArg()->getSurfaceArea() * size * size;
|
---|
[c67c65] | 144 | }
|
---|
| 145 |
|
---|
| 146 |
|
---|
[735940] | 147 | bool Resize_impl::isInside(const Vector& point) const{
|
---|
[b98a32] | 148 | return getArg()->isInside((1./size) * point);
|
---|
[6c438f] | 149 | }
|
---|
| 150 |
|
---|
[735940] | 151 | Vector Resize_impl::translateIn(const Vector& point) const{
|
---|
[b98a32] | 152 | return (1./size) * point;
|
---|
[5de9da] | 153 | }
|
---|
| 154 |
|
---|
[735940] | 155 | Vector Resize_impl::translateOutPos(const Vector& point) const{
|
---|
[5de9da] | 156 | return size * point;
|
---|
| 157 | }
|
---|
| 158 |
|
---|
[735940] | 159 | Vector Resize_impl::translateOutNormal(const Vector& point) const{
|
---|
[5de9da] | 160 | return point;
|
---|
[e09b70] | 161 | }
|
---|
| 162 |
|
---|
[b92e4a] | 163 | std::string Resize_impl::toString() const{
|
---|
[955b91] | 164 | std::stringstream sstr;
|
---|
[cfda65] | 165 | sstr << "resize(" << getArg()->toString() << "," << size << ")";
|
---|
| 166 | return sstr.str();
|
---|
| 167 | }
|
---|
| 168 |
|
---|
[e09b70] | 169 | Shape resize(const Shape &arg,double size){
|
---|
| 170 | Shape::impl_ptr impl = Shape::impl_ptr(new Resize_impl(getShapeImpl(arg),size));
|
---|
| 171 | return Shape(impl);
|
---|
| 172 | }
|
---|
| 173 |
|
---|
[5e588b5] | 174 | /*************************** translate *******************/
|
---|
| 175 |
|
---|
[e09b70] | 176 | Translate_impl::Translate_impl(const Shape::impl_ptr &_arg, const Vector &_offset) :
|
---|
[5de9da] | 177 | ShapeOpsBase_impl(_arg),offset(_offset)
|
---|
[e09b70] | 178 | {}
|
---|
| 179 |
|
---|
| 180 | Translate_impl::~Translate_impl(){}
|
---|
| 181 |
|
---|
[735940] | 182 | bool Translate_impl::isInside(const Vector& point) const{
|
---|
[6c438f] | 183 | return getArg()->isInside(point-offset);
|
---|
| 184 | }
|
---|
| 185 |
|
---|
[6acc2f3] | 186 | Vector Translate_impl::getCenter() const
|
---|
| 187 | {
|
---|
| 188 | return getArg()->getCenter()+offset;
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 | double Translate_impl::getRadius() const
|
---|
| 192 | {
|
---|
| 193 | return getArg()->getRadius();
|
---|
| 194 | }
|
---|
| 195 |
|
---|
[c67c65] | 196 | double Translate_impl::getVolume() const
|
---|
| 197 | {
|
---|
| 198 | return getArg()->getVolume();
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | double Translate_impl::getSurfaceArea() const
|
---|
| 202 | {
|
---|
| 203 | return getArg()->getSurfaceArea();
|
---|
| 204 | }
|
---|
[6acc2f3] | 205 |
|
---|
[735940] | 206 | Vector Translate_impl::translateIn(const Vector& point) const{
|
---|
[5de9da] | 207 | return point-offset;
|
---|
| 208 | }
|
---|
| 209 |
|
---|
[735940] | 210 | Vector Translate_impl::translateOutPos(const Vector& point) const{
|
---|
[5de9da] | 211 | return point+offset;
|
---|
| 212 | }
|
---|
| 213 |
|
---|
[735940] | 214 | Vector Translate_impl::translateOutNormal(const Vector& point) const{
|
---|
[5de9da] | 215 | return point;
|
---|
[e09b70] | 216 | }
|
---|
| 217 |
|
---|
[b92e4a] | 218 | std::string Translate_impl::toString() const{
|
---|
[955b91] | 219 | std::stringstream sstr;
|
---|
[cfda65] | 220 | sstr << "translate(" << getArg()->toString() << "," << offset << ")";
|
---|
[79dd0e] | 221 | return sstr.str();
|
---|
[cfda65] | 222 | }
|
---|
| 223 |
|
---|
[e09b70] | 224 | Shape translate(const Shape &arg, const Vector &offset){
|
---|
| 225 | Shape::impl_ptr impl = Shape::impl_ptr(new Translate_impl(getShapeImpl(arg),offset));
|
---|
| 226 | return Shape(impl);
|
---|
| 227 | }
|
---|
[5e588b5] | 228 |
|
---|
| 229 | /*********************** stretch ******************/
|
---|
| 230 |
|
---|
| 231 | Stretch_impl::Stretch_impl(const Shape::impl_ptr &_arg, const Vector &_factors) :
|
---|
[5de9da] | 232 | ShapeOpsBase_impl(_arg),factors(_factors)
|
---|
[5e588b5] | 233 | {
|
---|
| 234 | for(int i = NDIM;i--;){
|
---|
[84721b] | 235 | ASSERT(factors[i]>0.,"cannot stretch a shape by a negative amount");
|
---|
| 236 | reciFactors[i] = 1./factors[i];
|
---|
[5e588b5] | 237 | }
|
---|
| 238 | }
|
---|
| 239 |
|
---|
| 240 | Stretch_impl::~Stretch_impl(){}
|
---|
| 241 |
|
---|
[c67c65] | 242 | double Stretch_impl::getVolume() const
|
---|
| 243 | {
|
---|
| 244 | // TODO
|
---|
[08a09ed] | 245 | return getArg()->getVolume() * factors[0] * factors[1] * factors[2];
|
---|
[c67c65] | 246 | }
|
---|
| 247 |
|
---|
| 248 | double Stretch_impl::getSurfaceArea() const
|
---|
| 249 | {
|
---|
| 250 | // TODO
|
---|
[08a09ed] | 251 | return getArg()->getSurfaceArea() * pow(factors[0] * factors[1] * factors[2], 2./3.);
|
---|
[c67c65] | 252 | }
|
---|
| 253 |
|
---|
[735940] | 254 | bool Stretch_impl::isInside(const Vector& point) const{
|
---|
[5e588b5] | 255 | Vector helper=point;
|
---|
| 256 | helper.ScaleAll(reciFactors);
|
---|
[6c438f] | 257 | return getArg()->isInside(helper);
|
---|
| 258 | }
|
---|
| 259 |
|
---|
[735940] | 260 | Vector Stretch_impl::translateIn(const Vector& point) const{
|
---|
[5e588b5] | 261 | Vector helper=point;
|
---|
| 262 | helper.ScaleAll(reciFactors);
|
---|
[5de9da] | 263 | return helper;
|
---|
| 264 | }
|
---|
| 265 |
|
---|
[735940] | 266 | Vector Stretch_impl::translateOutPos(const Vector& point) const{
|
---|
[5de9da] | 267 | Vector helper=point;
|
---|
| 268 | helper.ScaleAll(factors);
|
---|
| 269 | return helper;
|
---|
| 270 | }
|
---|
| 271 |
|
---|
[735940] | 272 | Vector Stretch_impl::translateOutNormal(const Vector& point) const{
|
---|
[5de9da] | 273 | Vector helper=point;
|
---|
| 274 | // the normalFactors are derived from appearances of the factors
|
---|
| 275 | // with in the vectorproduct
|
---|
| 276 | Vector normalFactors;
|
---|
| 277 | normalFactors[0]=factors[1]*factors[2];
|
---|
| 278 | normalFactors[1]=factors[0]*factors[2];
|
---|
| 279 | normalFactors[2]=factors[0]*factors[1];
|
---|
| 280 | helper.ScaleAll(normalFactors);
|
---|
| 281 | return helper;
|
---|
[5e588b5] | 282 | }
|
---|
| 283 |
|
---|
[b92e4a] | 284 | std::string Stretch_impl::toString() const{
|
---|
[955b91] | 285 | std::stringstream sstr;
|
---|
[cfda65] | 286 | sstr << "stretch(" << getArg()->toString() << "," << factors << ")";
|
---|
| 287 | return sstr.str();
|
---|
| 288 | }
|
---|
| 289 |
|
---|
[5e588b5] | 290 | Shape stretch(const Shape &arg, const Vector &factors){
|
---|
| 291 | Shape::impl_ptr impl = Shape::impl_ptr(new Stretch_impl(getShapeImpl(arg),factors));
|
---|
| 292 | return Shape(impl);
|
---|
| 293 | }
|
---|
| 294 |
|
---|
| 295 | /************************* transform *****************/
|
---|
| 296 |
|
---|
[cca9ef] | 297 | Transform_impl::Transform_impl(const Shape::impl_ptr &_arg, const RealSpaceMatrix &_transformation) :
|
---|
[5de9da] | 298 | ShapeOpsBase_impl(_arg),transformation(_transformation)
|
---|
[5e588b5] | 299 | {
|
---|
| 300 | transformationInv = transformation.invert();
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | Transform_impl::~Transform_impl(){}
|
---|
| 304 |
|
---|
[c67c65] | 305 | double Transform_impl::getVolume() const
|
---|
| 306 | {
|
---|
[08a09ed] | 307 | return getArg()->getVolume() * transformation.determinant();
|
---|
[c67c65] | 308 | }
|
---|
| 309 |
|
---|
| 310 | double Transform_impl::getSurfaceArea() const
|
---|
| 311 | {
|
---|
[08a09ed] | 312 | return getArg()->getSurfaceArea() * pow(transformation.determinant(), 2./3.);
|
---|
[c67c65] | 313 | }
|
---|
| 314 |
|
---|
[735940] | 315 | bool Transform_impl::isInside(const Vector& point) const{
|
---|
[6c438f] | 316 | return getArg()->isInside(transformationInv * point);
|
---|
| 317 | }
|
---|
| 318 |
|
---|
[735940] | 319 | Vector Transform_impl::translateIn(const Vector& point) const{
|
---|
[5de9da] | 320 | return transformationInv * point;
|
---|
| 321 | }
|
---|
| 322 |
|
---|
[735940] | 323 | Vector Transform_impl::translateOutPos(const Vector& point) const{
|
---|
[5de9da] | 324 | return transformation * point;
|
---|
| 325 | }
|
---|
| 326 |
|
---|
[735940] | 327 | Vector Transform_impl::translateOutNormal(const Vector& point) const
|
---|
| 328 | {
|
---|
[cca9ef] | 329 | RealSpaceMatrix mat = transformation.invert().transpose();
|
---|
[5de9da] | 330 | return mat * point;
|
---|
[5e588b5] | 331 | }
|
---|
| 332 |
|
---|
[b92e4a] | 333 | std::string Transform_impl::toString() const{
|
---|
[955b91] | 334 | std::stringstream sstr;
|
---|
[cfda65] | 335 | sstr << "transform(" << getArg()->toString() << "," << transformation << ")";
|
---|
| 336 | return sstr.str();
|
---|
| 337 | }
|
---|
| 338 |
|
---|
[cca9ef] | 339 | Shape transform(const Shape &arg, const RealSpaceMatrix &transformation){
|
---|
[5e588b5] | 340 | Shape::impl_ptr impl = Shape::impl_ptr(new Transform_impl(getShapeImpl(arg),transformation));
|
---|
| 341 | return Shape(impl);
|
---|
| 342 | }
|
---|