source: src/Shapes/Shape.cpp@ 8b58ac

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 8b58ac 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
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
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/>.
21 */
22
23/*
24 * Shape.cpp
25 *
26 * Created on: Jun 18, 2010
27 * Author: crueger
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "CodePatterns/MemDebug.hpp"
36
37#include "CodePatterns/Assert.hpp"
38#include "LinearAlgebra/Vector.hpp"
39
40#include "Shapes/Shape.hpp"
41#include "Shapes/Shape_impl.hpp"
42#include "Shapes/ShapeExceptions.hpp"
43#include "Shapes/ShapeType.hpp"
44
45#include "Tesselation/ApproximateShapeArea.hpp"
46#include "Tesselation/ApproximateShapeVolume.hpp"
47
48#include <algorithm>
49#include <limits>
50#include <string>
51
52
53Shape::Shape(const Shape& src) :
54 impl(src.getImpl())
55{}
56
57Shape::~Shape(){}
58
59bool Shape::isInside(const Vector &point) const{
60 return impl->isInside(point);
61}
62
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
71Vector Shape::getCenter() const{
72 return impl->getCenter();
73}
74
75double Shape::getRadius() const{
76 return impl->getRadius();
77}
78
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 {
94 ApproximateShapeVolume Approximator(*this);
95 return Approximator();
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 {
114 ApproximateShapeArea Approximator(*this);
115 return Approximator();
116 }
117}
118
119LineSegmentSet Shape::getLineIntersections(const Line &line) const{
120 return impl->getLineIntersections(line);
121}
122
123std::vector<Vector> Shape::getHomogeneousPointsOnSurface(const size_t N) const {
124 return impl->getHomogeneousPointsOnSurface(N);
125}
126
127std::vector<Vector> Shape::getHomogeneousPointsInVolume(const size_t N) const {
128 return impl->getHomogeneousPointsInVolume(N);
129}
130
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
142bool Shape::operator==(const Shape &rhs) const{
143 return (this->getType() == rhs.getType());
144}
145
146std::string Shape::toString() const{
147 return impl->toString();
148}
149
150enum ShapeType Shape::getType() const{
151 return impl->getType();
152}
153
154Shape::impl_ptr Shape::getImpl() const{
155 return impl;
156}
157
158// allows arbitrary friendship, but only if implementation is known
159Shape::impl_ptr getShapeImpl(const Shape &shape){
160 return shape.getImpl();
161}
162
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
185bool AndShape_impl::isInside(const Vector &point) const{
186 return lhs->isInside(point) && rhs->isInside(point);
187}
188
189bool AndShape_impl::isOnSurface(const Vector &point) const{
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
202 return (lhs->isOnSurface(point) && rhs->isInside(point)) ||
203 (rhs->isOnSurface(point) && lhs->isInside(point));
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
221Vector AndShape_impl::getNormal(const Vector &point) const throw (NotOnSurfaceException){
222 Vector res;
223 if(!isOnSurface(point)){
224 throw NotOnSurfaceException() << ShapeVector(&point);
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
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
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
264LineSegmentSet AndShape_impl::getLineIntersections(const Line &line) const{
265 return intersect(lhs->getLineIntersections(line),rhs->getLineIntersections(line));
266}
267
268std::string AndShape_impl::toString() const{
269 return std::string("(") + lhs->toString() + std::string("&&") + rhs->toString() + std::string(")");
270}
271
272enum ShapeType AndShape_impl::getType() const{
273 return CombinedType;
274}
275
276std::vector<Vector> AndShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
277 std::vector<Vector> PointsOnSurface_lhs = lhs->getHomogeneousPointsOnSurface(N);
278 std::vector<Vector> PointsOnSurface_rhs = rhs->getHomogeneousPointsOnSurface(N);
279 std::vector<Vector> PointsOnSurface;
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
290 return PointsOnSurface;
291}
292
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
299
300Shape operator&&(const Shape &lhs,const Shape &rhs){
301 Shape::impl_ptr newImpl = Shape::impl_ptr(new AndShape_impl(getShapeImpl(lhs),getShapeImpl(rhs)));
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
313bool OrShape_impl::isInside(const Vector &point) const{
314 return rhs->isInside(point) || lhs->isInside(point);
315}
316
317bool OrShape_impl::isOnSurface(const Vector &point) const{
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
330 return (lhs->isOnSurface(point) && !rhs->isInside(point)) ||
331 (rhs->isOnSurface(point) && !lhs->isInside(point));
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
349Vector OrShape_impl::getNormal(const Vector &point) const throw (NotOnSurfaceException){
350 Vector res;
351 if(!isOnSurface(point)){
352 throw NotOnSurfaceException() << ShapeVector(&point);
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
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
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
388LineSegmentSet OrShape_impl::getLineIntersections(const Line &line) const{
389 return merge(lhs->getLineIntersections(line),rhs->getLineIntersections(line));
390}
391
392std::string OrShape_impl::toString() const{
393 return std::string("(") + lhs->toString() + std::string("||") + rhs->toString() + std::string(")");
394}
395
396enum ShapeType OrShape_impl::getType() const{
397 return CombinedType;
398}
399
400std::vector<Vector> OrShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
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
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
423Shape operator||(const Shape &lhs,const Shape &rhs){
424 Shape::impl_ptr newImpl = Shape::impl_ptr(new OrShape_impl(getShapeImpl(lhs),getShapeImpl(rhs)));
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
436bool NotShape_impl::isInside(const Vector &point) const{
437 return !arg->isInside(point);
438}
439
440bool NotShape_impl::isOnSurface(const Vector &point) const{
441 return arg->isOnSurface(point);
442}
443
444Vector NotShape_impl::getNormal(const Vector &point) const throw(NotOnSurfaceException){
445 return -1.*arg->getNormal(point);
446}
447
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
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
470LineSegmentSet NotShape_impl::getLineIntersections(const Line &line) const{
471 return invert(arg->getLineIntersections(line));
472}
473
474std::string NotShape_impl::toString() const{
475 return std::string("!") + arg->toString();
476}
477
478enum ShapeType NotShape_impl::getType() const{
479 return CombinedType;
480}
481
482std::vector<Vector> NotShape_impl::getHomogeneousPointsOnSurface(const size_t N) const {
483 // surfaces are the same, only normal direction is different
484 return arg->getHomogeneousPointsOnSurface(N);
485}
486
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
493Shape operator!(const Shape &arg){
494 Shape::impl_ptr newImpl = Shape::impl_ptr(new NotShape_impl(getShapeImpl(arg)));
495 return Shape(newImpl);
496}
497
498/**************** global operations *********************************/
499std::ostream &operator<<(std::ostream &ost,const Shape &shape){
500 ost << shape.toString();
501 return ost;
502}
Note: See TracBrowser for help on using the repository browser.