source: src/Shapes/Shape.cpp@ eff536

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since eff536 was 94d5ac6, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: As we use GSL internally, we are as of now required to use GPL v2 license.

  • GNU Scientific Library is used at every place in the code, especially the sub-package LinearAlgebra is based on it which in turn is used really everywhere in the remainder of MoleCuilder. Hence, we have to use the GPL license for the whole of MoleCuilder. In effect, GPL's COPYING was present all along and stated the terms of the GPL v2 license.
  • Hence, I added the default GPL v2 disclaimer to every source file and removed the note about a (actually missing) LICENSE file.
  • also, I added a help-redistribute action which again gives the disclaimer of the GPL v2.
  • also, I changed in the disclaimer that is printed at every program start in builder_init.cpp.
  • TEST: Added check on GPL statement present in every module to test CodeChecks project-disclaimer.
  • Property mode set to 100644
File size: 14.1 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[94d5ac6]5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
[bcf653]21 */
22
[997784]23/*
24 * Shape.cpp
25 *
26 * Created on: Jun 18, 2010
27 * Author: crueger
28 */
29
[bf3817]30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
[ad011c]35#include "CodePatterns/MemDebug.hpp"
[997784]36
[ad011c]37#include "CodePatterns/Assert.hpp"
[6c438f]38#include "LinearAlgebra/Vector.hpp"
39
[b94634]40#include "Shapes/Shape.hpp"
41#include "Shapes/Shape_impl.hpp"
42#include "Shapes/ShapeExceptions.hpp"
[b92e4a]43#include "Shapes/ShapeType.hpp"
[5de9da]44
[da1e92]45#include "Tesselation/ApproximateShapeArea.hpp"
46#include "Tesselation/ApproximateShapeVolume.hpp"
47
[6acc2f3]48#include <algorithm>
49#include <limits>
[cfda65]50#include <string>
51
52
[997784]53Shape::Shape(const Shape& src) :
54 impl(src.getImpl())
55{}
56
57Shape::~Shape(){}
58
[205d9b]59bool Shape::isInside(const Vector &point) const{
[997784]60 return impl->isInside(point);
61}
62
[5de9da]63bool Shape::isOnSurface(const Vector &point) const{
64 return impl->isOnSurface(point);
65}
66
67Vector Shape::getNormal(const Vector &point) const throw (NotOnSurfaceException){
68 return impl->getNormal(point);
69}
70
[6acc2f3]71Vector Shape::getCenter() const{
72 return impl->getCenter();
73}
74
75double Shape::getRadius() const{
76 return impl->getRadius();
77}
78
[c67c65]79/** Returns the volume of the Shape.
80 *
81 * If the underlying implementation does not have a working implementation,
82 * i.e. returns -1., then we use an approximate method to calculate the
83 * volume via a mesh of grid points and checking for isInside (basically
84 * a Monte-Carlo integration of the volume).
85 *
86 * \return volume of the shape
87 */
88double Shape::getVolume() const
89{
90 const double volume = impl->getVolume();
91 if (volume != -1.) {
92 return volume;
93 } else {
[da1e92]94 ApproximateShapeVolume Approximator(*this);
95 return Approximator();
[c67c65]96 }
97}
98
99/** Returns the surface area of the Shape.
100 *
101 * If the underlying implementation does not have a working implementation,
102 * i.e. returns -1., then we use the working filling of the shapes surface
103 * with points and subsequent tesselation and obtaining the approximate
104 * surface area therefrom.
105 *
106 * @return surface area of the Shape
107 */
108double Shape::getSurfaceArea() const
109{
110 const double surfacearea = impl->getSurfaceArea();
111 if (surfacearea != -1.) {
112 return surfacearea;
113 } else {
[da1e92]114 ApproximateShapeArea Approximator(*this);
115 return Approximator();
[c67c65]116 }
117}
118
[735940]119LineSegmentSet Shape::getLineIntersections(const Line &line) const{
[c6f395]120 return impl->getLineIntersections(line);
121}
122
[9c1c89]123std::vector<Vector> Shape::getHomogeneousPointsOnSurface(const size_t N) const {
[c5186e]124 return impl->getHomogeneousPointsOnSurface(N);
125}
126
[5a8d61]127std::vector<Vector> Shape::getHomogeneousPointsInVolume(const size_t N) const {
128 return impl->getHomogeneousPointsInVolume(N);
129}
130
[997784]131Shape::Shape(Shape::impl_ptr _impl) :
132 impl(_impl)
133{}
134
135Shape &Shape::operator=(const Shape& rhs){
136 if(&rhs!=this){
137 impl=rhs.getImpl();
138 }
139 return *this;
140}
141
[b92e4a]142bool Shape::operator==(const Shape &rhs) const{
143 return (this->getType() == rhs.getType());
144}
145
[cfda65]146std::string Shape::toString() const{
147 return impl->toString();
148}
149
[b92e4a]150enum ShapeType Shape::getType() const{
151 return impl->getType();
152}
153
[997784]154Shape::impl_ptr Shape::getImpl() const{
155 return impl;
156}
157
[e09b70]158// allows arbitrary friendship, but only if implementation is known
159Shape::impl_ptr getShapeImpl(const Shape &shape){
160 return shape.getImpl();
161}
162
[997784]163/***************************** Some simple Shapes ***************************/
164
165Shape Everywhere(){
166 static Shape::impl_ptr impl = Shape::impl_ptr(new Everywhere_impl());
167 return Shape(impl);
168}
169
170Shape Nowhere(){
171 static Shape::impl_ptr impl = Shape::impl_ptr(new Nowhere_impl());
172 return Shape(impl);
173}
174
175/****************************** Operators ***********************************/
176
177// AND
178
179AndShape_impl::AndShape_impl(const Shape::impl_ptr &_lhs, const Shape::impl_ptr &_rhs) :
180 lhs(_lhs),rhs(_rhs)
181{}
182
183AndShape_impl::~AndShape_impl(){}
184
[735940]185bool AndShape_impl::isInside(const Vector &point) const{
[997784]186 return lhs->isInside(point) && rhs->isInside(point);
187}
188
[735940]189bool AndShape_impl::isOnSurface(const Vector &point) const{
[5de9da]190 // check the number of surfaces that this point is on
191 int surfaces =0;
192 surfaces += lhs->isOnSurface(point);
193 surfaces += rhs->isOnSurface(point);
194
195 switch(surfaces){
196 case 0:
197 return false;
198 // no break necessary
199 case 1:
200 // if it is inside for the object where it does not lie on
201 // the surface the whole point lies inside
[ef84ca]202 return (lhs->isOnSurface(point) && rhs->isInside(point)) ||
203 (rhs->isOnSurface(point) && lhs->isInside(point));
[5de9da]204 // no break necessary
205 case 2:
206 {
207 // it lies on both Shapes... could be an edge or an inner point
208 // test the direction of the normals
209 Vector direction=lhs->getNormal(point)+rhs->getNormal(point);
210 // if the directions are opposite we lie on the inside
211 return !direction.IsZero();
212 }
213 // no break necessary
214 default:
215 // if this happens there is something wrong
216 ASSERT(0,"Default case should have never been used");
217 }
218 return false; // never reached
219}
220
[735940]221Vector AndShape_impl::getNormal(const Vector &point) const throw (NotOnSurfaceException){
[5de9da]222 Vector res;
223 if(!isOnSurface(point)){
[b94634]224 throw NotOnSurfaceException() << ShapeVector(&point);
[5de9da]225 }
226 res += lhs->isOnSurface(point)?lhs->getNormal(point):zeroVec;
227 res += rhs->isOnSurface(point)?rhs->getNormal(point):zeroVec;
228 res.Normalize();
229 return res;
230}
231
[6acc2f3]232Vector AndShape_impl::getCenter() const
233{
234 // calculate closest position on sphere surface to other center ..
235 const Vector rhsDistance = rhs->getCenter() + rhs->getRadius()*((lhs->getCenter() - rhs->getCenter()).getNormalized());
236 const Vector lhsDistance = lhs->getCenter() + lhs->getRadius()*((rhs->getCenter() - lhs->getCenter()).getNormalized());
237 // .. and then it's right in between those two
238 return 0.5*(rhsDistance + lhsDistance);
239}
240
241double AndShape_impl::getRadius() const
242{
243 const double distance = (lhs->getCenter() - rhs->getCenter()).Norm();
244 const double minradii = std::min(lhs->getRadius(), rhs->getRadius());
245 // if no intersection
246 if (distance > (lhs->getRadius() + rhs->getRadius()))
247 return 0.;
248 else // if intersection it can only be the smaller one
249 return minradii;
250}
251
[c67c65]252double AndShape_impl::getVolume() const
253{
254 // TODO
255 return -1.;
256}
257
258double AndShape_impl::getSurfaceArea() const
259{
260 // TODO
261 return -1.;
262}
263
[735940]264LineSegmentSet AndShape_impl::getLineIntersections(const Line &line) const{
[c6f395]265 return intersect(lhs->getLineIntersections(line),rhs->getLineIntersections(line));
266}
267
[b92e4a]268std::string AndShape_impl::toString() const{
[955b91]269 return std::string("(") + lhs->toString() + std::string("&&") + rhs->toString() + std::string(")");
[cfda65]270}
271
[b92e4a]272enum ShapeType AndShape_impl::getType() const{
273 return CombinedType;
274}
275
[9c1c89]276std::vector<Vector> AndShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
[23bade]277 std::vector<Vector> PointsOnSurface_lhs = lhs->getHomogeneousPointsOnSurface(N);
278 std::vector<Vector> PointsOnSurface_rhs = rhs->getHomogeneousPointsOnSurface(N);
[c5186e]279 std::vector<Vector> PointsOnSurface;
[23bade]280
281 for (std::vector<Vector>::const_iterator iter = PointsOnSurface_lhs.begin(); iter != PointsOnSurface_lhs.end(); ++iter) {
282 if (rhs->isInside(*iter))
283 PointsOnSurface.push_back(*iter);
284 }
285 for (std::vector<Vector>::const_iterator iter = PointsOnSurface_rhs.begin(); iter != PointsOnSurface_rhs.end(); ++iter) {
286 if (lhs->isInside(*iter))
287 PointsOnSurface.push_back(*iter);
288 }
289
[c5186e]290 return PointsOnSurface;
291}
292
[5a8d61]293std::vector<Vector> AndShape_impl::getHomogeneousPointsInVolume(const size_t N) const {
294 ASSERT(0,
295 "AndShape_impl::getHomogeneousPointsInVolume() - not implemented.");
296 return std::vector<Vector>();
297}
298
[c5186e]299
[997784]300Shape operator&&(const Shape &lhs,const Shape &rhs){
[e09b70]301 Shape::impl_ptr newImpl = Shape::impl_ptr(new AndShape_impl(getShapeImpl(lhs),getShapeImpl(rhs)));
[997784]302 return Shape(newImpl);
303}
304
305// OR
306
307OrShape_impl::OrShape_impl(const Shape::impl_ptr &_lhs, const Shape::impl_ptr &_rhs) :
308 lhs(_lhs),rhs(_rhs)
309{}
310
311OrShape_impl::~OrShape_impl(){}
312
[735940]313bool OrShape_impl::isInside(const Vector &point) const{
[997784]314 return rhs->isInside(point) || lhs->isInside(point);
315}
316
[735940]317bool OrShape_impl::isOnSurface(const Vector &point) const{
[5de9da]318 // check the number of surfaces that this point is on
319 int surfaces =0;
320 surfaces += lhs->isOnSurface(point);
321 surfaces += rhs->isOnSurface(point);
322
323 switch(surfaces){
324 case 0:
325 return false;
326 // no break necessary
327 case 1:
328 // if it is inside for the object where it does not lie on
329 // the surface the whole point lies inside
[ef84ca]330 return (lhs->isOnSurface(point) && !rhs->isInside(point)) ||
331 (rhs->isOnSurface(point) && !lhs->isInside(point));
[5de9da]332 // no break necessary
333 case 2:
334 {
335 // it lies on both Shapes... could be an edge or an inner point
336 // test the direction of the normals
337 Vector direction=lhs->getNormal(point)+rhs->getNormal(point);
338 // if the directions are opposite we lie on the inside
339 return !direction.IsZero();
340 }
341 // no break necessary
342 default:
343 // if this happens there is something wrong
344 ASSERT(0,"Default case should have never been used");
345 }
346 return false; // never reached
347}
348
[735940]349Vector OrShape_impl::getNormal(const Vector &point) const throw (NotOnSurfaceException){
[5de9da]350 Vector res;
351 if(!isOnSurface(point)){
[b94634]352 throw NotOnSurfaceException() << ShapeVector(&point);
[5de9da]353 }
354 res += lhs->isOnSurface(point)?lhs->getNormal(point):zeroVec;
355 res += rhs->isOnSurface(point)?rhs->getNormal(point):zeroVec;
356 res.Normalize();
357 return res;
358}
359
[6acc2f3]360Vector OrShape_impl::getCenter() const
361{
362 // calculate furthest position on sphere surface to other center ..
363 const Vector rhsDistance = rhs->getCenter() + rhs->getRadius()*((rhs->getCenter() - lhs->getCenter()).getNormalized());
364 const Vector lhsDistance = lhs->getCenter() + lhs->getRadius()*((lhs->getCenter() - rhs->getCenter()).getNormalized());
365 // .. and then it's right in between those two
366 return .5*(rhsDistance + lhsDistance);
367}
368
369double OrShape_impl::getRadius() const
370{
371 const Vector rhsDistance = rhs->getCenter() + rhs->getRadius()*((rhs->getCenter() - lhs->getCenter()).getNormalized());
372 const Vector lhsDistance = lhs->getCenter() + lhs->getRadius()*((lhs->getCenter() - rhs->getCenter()).getNormalized());
373 return .5*(rhsDistance - lhsDistance).Norm();
374}
375
[c67c65]376double OrShape_impl::getVolume() const
377{
378 // TODO
379 return -1.;
380}
381
382double OrShape_impl::getSurfaceArea() const
383{
384 // TODO
385 return -1.;
386}
387
[735940]388LineSegmentSet OrShape_impl::getLineIntersections(const Line &line) const{
[c6f395]389 return merge(lhs->getLineIntersections(line),rhs->getLineIntersections(line));
390}
391
[b92e4a]392std::string OrShape_impl::toString() const{
[955b91]393 return std::string("(") + lhs->toString() + std::string("||") + rhs->toString() + std::string(")");
[cfda65]394}
395
[b92e4a]396enum ShapeType OrShape_impl::getType() const{
397 return CombinedType;
398}
399
[9c1c89]400std::vector<Vector> OrShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
[c5186e]401 std::vector<Vector> PointsOnSurface_lhs = lhs->getHomogeneousPointsOnSurface(N);
402 std::vector<Vector> PointsOnSurface_rhs = rhs->getHomogeneousPointsOnSurface(N);
403 std::vector<Vector> PointsOnSurface;
404
405 for (std::vector<Vector>::const_iterator iter = PointsOnSurface_lhs.begin(); iter != PointsOnSurface_lhs.end(); ++iter) {
406 if (!rhs->isInside(*iter))
407 PointsOnSurface.push_back(*iter);
408 }
409 for (std::vector<Vector>::const_iterator iter = PointsOnSurface_rhs.begin(); iter != PointsOnSurface_rhs.end(); ++iter) {
410 if (!lhs->isInside(*iter))
411 PointsOnSurface.push_back(*iter);
412 }
413
414 return PointsOnSurface;
415}
416
[5a8d61]417std::vector<Vector> OrShape_impl::getHomogeneousPointsInVolume(const size_t N) const {
418 ASSERT(0,
419 "OrShape_impl::getHomogeneousPointsInVolume() - not implemented.");
420 return std::vector<Vector>();
421}
422
[997784]423Shape operator||(const Shape &lhs,const Shape &rhs){
[e09b70]424 Shape::impl_ptr newImpl = Shape::impl_ptr(new OrShape_impl(getShapeImpl(lhs),getShapeImpl(rhs)));
[997784]425 return Shape(newImpl);
426}
427
428// NOT
429
430NotShape_impl::NotShape_impl(const Shape::impl_ptr &_arg) :
431 arg(_arg)
432{}
433
434NotShape_impl::~NotShape_impl(){}
435
[735940]436bool NotShape_impl::isInside(const Vector &point) const{
[997784]437 return !arg->isInside(point);
438}
439
[735940]440bool NotShape_impl::isOnSurface(const Vector &point) const{
[5de9da]441 return arg->isOnSurface(point);
442}
443
[735940]444Vector NotShape_impl::getNormal(const Vector &point) const throw(NotOnSurfaceException){
[b94634]445 return -1.*arg->getNormal(point);
[5de9da]446}
447
[6acc2f3]448Vector NotShape_impl::getCenter() const
449{
450 return arg->getCenter();
451}
452
453double NotShape_impl::getRadius() const
454{
455 return std::numeric_limits<double>::infinity();
456}
457
[c67c65]458double NotShape_impl::getVolume() const
459{
460 // TODO
461 return -1.; //-arg->getVolume();
462}
463
464double NotShape_impl::getSurfaceArea() const
465{
466 // TODO
467 return -1.; // -arg->getSurfaceArea();
468}
469
[735940]470LineSegmentSet NotShape_impl::getLineIntersections(const Line &line) const{
[c6f395]471 return invert(arg->getLineIntersections(line));
472}
473
[b92e4a]474std::string NotShape_impl::toString() const{
[955b91]475 return std::string("!") + arg->toString();
[cfda65]476}
477
[b92e4a]478enum ShapeType NotShape_impl::getType() const{
479 return CombinedType;
480}
481
[9c1c89]482std::vector<Vector> NotShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
[c5186e]483 // surfaces are the same, only normal direction is different
484 return arg->getHomogeneousPointsOnSurface(N);
485}
486
[5a8d61]487std::vector<Vector> NotShape_impl::getHomogeneousPointsInVolume(const size_t N) const {
488 ASSERT(0,
489 "NotShape_impl::getHomogeneousPointsInVolume() - not implemented.");
490 return std::vector<Vector>();
491}
492
[997784]493Shape operator!(const Shape &arg){
[e09b70]494 Shape::impl_ptr newImpl = Shape::impl_ptr(new NotShape_impl(getShapeImpl(arg)));
[997784]495 return Shape(newImpl);
496}
[cfda65]497
498/**************** global operations *********************************/
[955b91]499std::ostream &operator<<(std::ostream &ost,const Shape &shape){
[cfda65]500 ost << shape.toString();
501 return ost;
502}
Note: See TracBrowser for help on using the repository browser.