/* * 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. */ /* * BaseShapes_impl.cpp * * Created on: Jun 18, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "Shapes/BaseShapes.hpp" #include "Shapes/BaseShapes_impl.hpp" #include "Shapes/ShapeExceptions.hpp" #include "Shapes/ShapeOps.hpp" #include "Helpers/defs.hpp" #include "CodePatterns/Assert.hpp" #include "LinearAlgebra/Vector.hpp" #include "LinearAlgebra/Line.hpp" #include "LinearAlgebra/Plane.hpp" #include "LinearAlgebra/LineSegment.hpp" #include "LinearAlgebra/LineSegmentSet.hpp" #include #include bool Sphere_impl::isInside(const Vector &point){ return point.NormSquared()<=1; } bool Sphere_impl::isOnSurface(const Vector &point){ return fabs(point.NormSquared()-1) intersections = line.getSphereIntersections(); if(intersections.size()==2){ res.insert(LineSegment(intersections[0],intersections[1])); } return res; } string Sphere_impl::toString(){ return "Sphere()"; } /** * algorithm taken from http://www.cgafaq.info/wiki/Evenly_distributed_points_on_sphere * \param N number of points on surface */ std::vector Sphere_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface; double PI=3.14159265358979323846; double a=4*PI/N; double d= sqrt(a); int Mtheta=int(PI/d); double dtheta=PI/Mtheta; double dphi=a/dtheta; for (int m=0; m=0 && point[0]<=1) && (point[1]>=0 && point[1]<=1) && (point[2]>=0 && point[2]<=1); } bool Cuboid_impl::isOnSurface(const Vector &point){ bool retVal = isInside(point); // test all borders of the cuboid // double fabs retVal = retVal && (((fabs(point[0]-1.) < MYEPSILON) || (fabs(point[0]) < MYEPSILON)) || ((fabs(point[1]-1.) < MYEPSILON) || (fabs(point[1]) < MYEPSILON)) || ((fabs(point[2]-1.) < MYEPSILON) || (fabs(point[2]) < MYEPSILON))); return retVal; } Vector Cuboid_impl::getNormal(const Vector &point) throw(NotOnSurfaceException){ if(!isOnSurface(point)){ throw NotOnSurfaceException() << ShapeVector(&point); } Vector res; // figure out on which sides the Vector lies (maximum 3, when it is in a corner) for(int i=NDIM;i--;){ if(fabs(fabs(point[i])-1)=1 && res.NormSquared()<=3,"To many or to few sides found for this Vector"); res.Normalize(); return res; } LineSegmentSet Cuboid_impl::getLineIntersections(const Line &line){ LineSegmentSet res(line); // get the intersection on each of the six faces vector intersections; intersections.resize(2); int c=0; int x[2]={-1,+1}; for(int i=NDIM;i--;){ for(int p=0;p<2;++p){ if(c==2) goto end; // I know this sucks, but breaking two loops is stupid Vector base; base[i]=x[p]; // base now points to the surface and is normal to it at the same time Plane p(base,base); Vector intersection = p.GetIntersection(line); if(isInside(intersection)){ // if we have a point on the edge it might already be contained if(c==1 && intersections[0]==intersection) continue; intersections[c++]=intersection; } } } end: if(c==2){ res.insert(LineSegment(intersections[0],intersections[1])); } return res; } string Cuboid_impl::toString(){ return "Cuboid()"; } /** * \param N number of points on surface */ std::vector Cuboid_impl::getHomogeneousPointsOnSurface(const size_t N) const { std::vector PointsOnSurface; ASSERT(false, "Cuboid_impl::getHomogeneousPointsOnSurface() not implemented yet"); return PointsOnSurface; } Shape Cuboid(){ Shape::impl_ptr impl = Shape::impl_ptr(new Cuboid_impl()); return Shape(impl); } Shape Cuboid(const Vector &corner1, const Vector &corner2){ // make sure the two edges are upper left front and lower right back Vector sortedC1; Vector sortedC2; for(int i=NDIM;i--;){ sortedC1[i] = min(corner1[i],corner2[i]); sortedC2[i] = max(corner1[i],corner2[i]); ASSERT(corner1[i]!=corner2[i],"Given points for cuboid edges did not define a valid space"); } // get the middle point Vector middle = (1./2.)*(sortedC1+sortedC2); Vector factors = sortedC2-middle; return translate(stretch(Cuboid(),factors),middle); }