source: src/Fragmentation/Exporters/SphericalPointDistribution.cpp@ 80c119

Last change on this file since 80c119 was 80c119, checked in by Frederik Heber <heber@…>, 9 years ago

Extended SphericalPointDistribution::Polygon_t to WeightedPolygon_t.

  • contains additionally the weights from the already present points.
  • in order to deal sensibly with present bonds of higher degree (>1) that shift neighboring occupied orbitals even further away, we additionally pass on the bond degree. This indicates how many points of the N points have to be accumulated for this on present bond.
  • TESTS: Regression test FragmentMolecule-cylces failing for the moment.
  • Property mode set to 100644
File size: 23.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2014 Frederik Heber. 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 * SphericalPointDistribution.cpp
25 *
26 * Created on: May 30, 2014
27 * Author: heber
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 "SphericalPointDistribution.hpp"
38
39#include "CodePatterns/Assert.hpp"
40#include "CodePatterns/IteratorAdaptors.hpp"
41#include "CodePatterns/Log.hpp"
42#include "CodePatterns/toString.hpp"
43
44#include <algorithm>
45#include <boost/math/quaternion.hpp>
46#include <cmath>
47#include <functional>
48#include <iterator>
49#include <limits>
50#include <list>
51#include <vector>
52#include <map>
53
54#include "LinearAlgebra/Line.hpp"
55#include "LinearAlgebra/Plane.hpp"
56#include "LinearAlgebra/RealSpaceMatrix.hpp"
57#include "LinearAlgebra/Vector.hpp"
58
59// static entities
60const double SphericalPointDistribution::SQRT_3(sqrt(3.0));
61const double SphericalPointDistribution::warn_amplitude = 1e-2;
62
63typedef std::vector<double> DistanceArray_t;
64
65inline
66DistanceArray_t calculatePairwiseDistances(
67 const std::vector<Vector> &_points,
68 const SphericalPointDistribution::IndexList_t &_indices
69 )
70{
71 DistanceArray_t result;
72 for (SphericalPointDistribution::IndexList_t::const_iterator firstiter = _indices.begin();
73 firstiter != _indices.end(); ++firstiter) {
74 for (SphericalPointDistribution::IndexList_t::const_iterator seconditer = firstiter;
75 seconditer != _indices.end(); ++seconditer) {
76 if (firstiter == seconditer)
77 continue;
78 const double distance = (_points[*firstiter] - _points[*seconditer]).NormSquared();
79 result.push_back(distance);
80 }
81 }
82 return result;
83}
84
85// class generator: taken from www.cplusplus.com example std::generate
86struct c_unique {
87 int current;
88 c_unique() {current=0;}
89 int operator()() {return current++;}
90} UniqueNumber;
91
92/** Returns squared L2 error of the given \a _Matching.
93 *
94 * We compare the pair-wise distances of each associated matching
95 * and check whether these distances each match between \a _old and
96 * \a _new.
97 *
98 * \param _old first set of returnpolygon (fewer or equal to \a _new)
99 * \param _new second set of returnpolygon
100 * \param _Matching matching between the two sets
101 * \return pair with L1 and squared L2 error
102 */
103std::pair<double, double> SphericalPointDistribution::calculateErrorOfMatching(
104 const std::vector<Vector> &_old,
105 const std::vector<Vector> &_new,
106 const IndexList_t &_Matching)
107{
108 std::pair<double, double> errors( std::make_pair( 0., 0. ) );
109
110 if (_Matching.size() > 1) {
111 LOG(3, "INFO: Matching is " << _Matching);
112
113 // calculate all pair-wise distances
114 IndexList_t keys(_Matching.size());
115 std::generate (keys.begin(), keys.end(), UniqueNumber);
116 const DistanceArray_t firstdistances = calculatePairwiseDistances(_old, keys);
117 const DistanceArray_t seconddistances = calculatePairwiseDistances(_new, _Matching);
118
119 ASSERT( firstdistances.size() == seconddistances.size(),
120 "calculateL2ErrorOfMatching() - mismatch in pair-wise distance array sizes.");
121 DistanceArray_t::const_iterator firstiter = firstdistances.begin();
122 DistanceArray_t::const_iterator seconditer = seconddistances.begin();
123 for (;(firstiter != firstdistances.end()) && (seconditer != seconddistances.end());
124 ++firstiter, ++seconditer) {
125 const double gap = *firstiter - *seconditer;
126 // L1 error
127 if (errors.first < gap)
128 errors.first = gap;
129 // L2 error
130 errors.second += gap*gap;
131 }
132 } else
133 ELOG(3, "calculateErrorOfMatching() - Given matching's size is less than 2.");
134 LOG(3, "INFO: Resulting errors for matching (L1, L2): "
135 << errors.first << "," << errors.second << ".");
136
137 return errors;
138}
139
140SphericalPointDistribution::Polygon_t SphericalPointDistribution::removeMatchingPoints(
141 const VectorArray_t &_points,
142 const IndexList_t &_matchingindices
143 )
144{
145 SphericalPointDistribution::Polygon_t remainingreturnpolygon;
146 IndexArray_t indices(_matchingindices.begin(), _matchingindices.end());
147 std::sort(indices.begin(), indices.end());
148 LOG(4, "DEBUG: sorted matching is " << indices);
149 IndexArray_t remainingindices(_points.size(), -1);
150 std::generate(remainingindices.begin(), remainingindices.end(), UniqueNumber);
151 IndexArray_t::iterator remainiter = std::set_difference(
152 remainingindices.begin(), remainingindices.end(),
153 indices.begin(), indices.end(),
154 remainingindices.begin());
155 remainingindices.erase(remainiter, remainingindices.end());
156 LOG(4, "DEBUG: remaining indices are " << remainingindices);
157 for (IndexArray_t::const_iterator iter = remainingindices.begin();
158 iter != remainingindices.end(); ++iter) {
159 remainingreturnpolygon.push_back(_points[*iter]);
160 }
161
162 return remainingreturnpolygon;
163}
164
165/** Recursive function to go through all possible matchings.
166 *
167 * \param _MCS structure holding global information to the recursion
168 * \param _matching current matching being build up
169 * \param _indices contains still available indices
170 * \param _matchingsize
171 */
172void SphericalPointDistribution::recurseMatchings(
173 MatchingControlStructure &_MCS,
174 IndexList_t &_matching,
175 IndexList_t _indices,
176 unsigned int _matchingsize)
177{
178 LOG(4, "DEBUG: Recursing with current matching " << _matching
179 << ", remaining indices " << _indices
180 << ", and sought size " << _matching.size()+_matchingsize);
181 //!> threshold for L1 error below which matching is immediately acceptable
182 const double L1THRESHOLD = 1e-2;
183 if (!_MCS.foundflag) {
184 LOG(4, "DEBUG: Current matching has size " << _matching.size() << ", places left " << _matchingsize);
185 if (_matchingsize > 0) {
186 // go through all indices
187 for (IndexList_t::iterator iter = _indices.begin();
188 (iter != _indices.end()) && (!_MCS.foundflag);) {
189 // add index to matching
190 _matching.push_back(*iter);
191 LOG(5, "DEBUG: Adding " << *iter << " to matching.");
192 // remove index but keep iterator to position (is the next to erase element)
193 IndexList_t::iterator backupiter = _indices.erase(iter);
194 // recurse with decreased _matchingsize
195 recurseMatchings(_MCS, _matching, _indices, _matchingsize-1);
196 // re-add chosen index and reset index to new position
197 _indices.insert(backupiter, _matching.back());
198 iter = backupiter;
199 // remove index from _matching to make space for the next one
200 _matching.pop_back();
201 }
202 // gone through all indices then exit recursion
203 if (_matching.empty())
204 _MCS.foundflag = true;
205 } else {
206 LOG(3, "INFO: Found matching " << _matching);
207 // calculate errors
208 std::pair<double, double> errors = calculateErrorOfMatching(
209 _MCS.oldpoints, _MCS.newpoints, _matching);
210 if (errors.first < L1THRESHOLD) {
211 _MCS.bestmatching = _matching;
212 _MCS.foundflag = true;
213 } else if (_MCS.bestL2 > errors.second) {
214 _MCS.bestmatching = _matching;
215 _MCS.bestL2 = errors.second;
216 }
217 }
218 }
219}
220
221/** Decides by an orthonormal third vector whether the sign of the rotation
222 * angle should be negative or positive.
223 *
224 * \return -1 or 1
225 */
226inline
227double determineSignOfRotation(
228 const Vector &_oldPosition,
229 const Vector &_newPosition,
230 const Vector &_RotationAxis
231 )
232{
233 Vector dreiBein(_oldPosition);
234 dreiBein.VectorProduct(_RotationAxis);
235 dreiBein.Normalize();
236 const double sign =
237 (dreiBein.ScalarProduct(_newPosition) < 0.) ? -1. : +1.;
238 LOG(6, "DEBUG: oldCenter on plane is " << _oldPosition
239 << ", newCenter in plane is " << _newPosition
240 << ", and dreiBein is " << dreiBein);
241 return sign;
242}
243
244/** Finds combinatorially the best matching between points in \a _polygon
245 * and \a _newpolygon.
246 *
247 * We find the matching with the smallest L2 error, where we break when we stumble
248 * upon a matching with zero error.
249 *
250 * \sa recurseMatchings() for going through all matchings
251 *
252 * \param _polygon here, we have indices 0,1,2,...
253 * \param _newpolygon and here we need to find the correct indices
254 * \return list of indices: first in \a _polygon goes to first index for \a _newpolygon
255 */
256SphericalPointDistribution::IndexList_t SphericalPointDistribution::findBestMatching(
257 const SphericalPointDistribution::WeightedPolygon_t &_polygon,
258 const SphericalPointDistribution::Polygon_t &_newpolygon
259 )
260{
261 MatchingControlStructure MCS;
262 MCS.foundflag = false;
263 MCS.bestL2 = std::numeric_limits<double>::max();
264 for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
265 iter != _polygon.end(); ++iter)
266 MCS.oldpoints.push_back(iter->first);
267 MCS.newpoints.insert(MCS.newpoints.begin(), _newpolygon.begin(),_newpolygon.end() );
268
269 // search for bestmatching combinatorially
270 {
271 // translate polygon into vector to enable index addressing
272 IndexList_t indices(_newpolygon.size());
273 std::generate(indices.begin(), indices.end(), UniqueNumber);
274 IndexList_t matching;
275
276 // walk through all matchings
277 const unsigned int matchingsize = _polygon.size();
278 ASSERT( matchingsize <= indices.size(),
279 "SphericalPointDistribution::matchSphericalPointDistributions() - not enough new points to choose for matching to old ones.");
280 recurseMatchings(MCS, matching, indices, matchingsize);
281 }
282 return MCS.bestmatching;
283}
284
285inline
286Vector calculateCenter(
287 const SphericalPointDistribution::VectorArray_t &_positions,
288 const SphericalPointDistribution::IndexList_t &_indices)
289{
290 Vector Center;
291 Center.Zero();
292 for (SphericalPointDistribution::IndexList_t::const_iterator iter = _indices.begin();
293 iter != _indices.end(); ++iter)
294 Center += _positions[*iter];
295 if (!_indices.empty())
296 Center *= 1./(double)_indices.size();
297
298 return Center;
299}
300
301inline
302void calculateOldAndNewCenters(
303 Vector &_oldCenter,
304 Vector &_newCenter,
305 const SphericalPointDistribution::VectorArray_t &_referencepositions,
306 const SphericalPointDistribution::VectorArray_t &_currentpositions,
307 const SphericalPointDistribution::IndexList_t &_bestmatching)
308{
309 const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3);
310 SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1);
311 std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber);
312 _oldCenter = calculateCenter(_referencepositions, continuousIds);
313 // C++11 defines a copy_n function ...
314 SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin();
315 std::advance(enditer, NumberIds);
316 SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1);
317 std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin());
318 _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds);
319}
320
321SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPlaneAligningRotation(
322 const VectorArray_t &_referencepositions,
323 const VectorArray_t &_currentpositions,
324 const IndexList_t &_bestmatching
325 )
326{
327 bool dontcheck = false;
328 // initialize to no rotation
329 Rotation_t Rotation;
330 Rotation.first.Zero();
331 Rotation.first[0] = 1.;
332 Rotation.second = 0.;
333
334 // calculate center of triangle/line/point consisting of first points of matching
335 Vector oldCenter;
336 Vector newCenter;
337 calculateOldAndNewCenters(
338 oldCenter, newCenter,
339 _referencepositions, _currentpositions, _bestmatching);
340
341 if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
342 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter);
343 oldCenter.Normalize();
344 newCenter.Normalize();
345 if (!oldCenter.IsEqualTo(newCenter)) {
346 // calculate rotation axis and angle
347 Rotation.first = oldCenter;
348 Rotation.first.VectorProduct(newCenter);
349 Rotation.second = oldCenter.Angle(newCenter); // /(M_PI/2.);
350 } else {
351 // no rotation required anymore
352 }
353 } else {
354 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter);
355 if ((oldCenter.IsZero()) && (newCenter.IsZero())) {
356 // either oldCenter or newCenter (or both) is directly at origin
357 if (_bestmatching.size() == 2) {
358 // line case
359 Vector oldPosition = _currentpositions[*_bestmatching.begin()];
360 Vector newPosition = _referencepositions[0];
361 // check whether we need to rotate at all
362 if (!oldPosition.IsEqualTo(newPosition)) {
363 Rotation.first = oldPosition;
364 Rotation.first.VectorProduct(newPosition);
365 // orientation will fix the sign here eventually
366 Rotation.second = oldPosition.Angle(newPosition);
367 } else {
368 // no rotation required anymore
369 }
370 } else {
371 // triangle case
372 // both triangles/planes have same center, hence get axis by
373 // VectorProduct of Normals
374 Plane newplane(_referencepositions[0], _referencepositions[1], _referencepositions[2]);
375 VectorArray_t vectors;
376 for (IndexList_t::const_iterator iter = _bestmatching.begin();
377 iter != _bestmatching.end(); ++iter)
378 vectors.push_back(_currentpositions[*iter]);
379 Plane oldplane(vectors[0], vectors[1], vectors[2]);
380 Vector oldPosition = oldplane.getNormal();
381 Vector newPosition = newplane.getNormal();
382 // check whether we need to rotate at all
383 if (!oldPosition.IsEqualTo(newPosition)) {
384 Rotation.first = oldPosition;
385 Rotation.first.VectorProduct(newPosition);
386 Rotation.first.Normalize();
387
388 // construct reference vector to determine direction of rotation
389 const double sign = determineSignOfRotation(oldPosition, newPosition, Rotation.first);
390 Rotation.second = sign * oldPosition.Angle(newPosition);
391 LOG(5, "DEBUG: Rotating plane normals by " << Rotation.second
392 << " around axis " << Rotation.first);
393 } else {
394 // else do nothing
395 }
396 }
397 } else {
398 // TODO: we can't do anything here, but this case needs to be dealt with when
399 // we have no ideal geometries anymore
400 if ((oldCenter-newCenter).Norm() > warn_amplitude)
401 ELOG(2, "oldCenter is " << oldCenter << ", yet newCenter is " << newCenter);
402 // else they are considered close enough
403 dontcheck = true;
404 }
405 }
406
407#ifndef NDEBUG
408 // check: rotation brings newCenter onto oldCenter position
409 if (!dontcheck) {
410 Line Axis(zeroVec, Rotation.first);
411 Vector test = Axis.rotateVector(newCenter, Rotation.second);
412 LOG(4, "CHECK: rotated newCenter is " << test
413 << ", oldCenter is " << oldCenter);
414 ASSERT( (test - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4,
415 "matchSphericalPointDistributions() - rotation does not work as expected by "
416 +toString((test - oldCenter).NormSquared())+".");
417 }
418#endif
419
420 return Rotation;
421}
422
423SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPointAligningRotation(
424 const VectorArray_t &remainingold,
425 const VectorArray_t &remainingnew,
426 const IndexList_t &_bestmatching)
427{
428 // initialize rotation to zero
429 Rotation_t Rotation;
430 Rotation.first.Zero();
431 Rotation.first[0] = 1.;
432 Rotation.second = 0.;
433
434 // recalculate center
435 Vector oldCenter;
436 Vector newCenter;
437 calculateOldAndNewCenters(
438 oldCenter, newCenter,
439 remainingold, remainingnew, _bestmatching);
440
441 Vector oldPosition = remainingnew[*_bestmatching.begin()];
442 Vector newPosition = remainingold[0];
443 LOG(6, "DEBUG: oldPosition is " << oldPosition << " and newPosition is " << newPosition);
444 if (!oldPosition.IsEqualTo(newPosition)) {
445 if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
446 oldCenter.Normalize(); // note weighted sum of normalized weight is not normalized
447 Rotation.first = oldCenter;
448 LOG(6, "DEBUG: Picking normalized oldCenter as Rotation.first " << oldCenter);
449 oldPosition.ProjectOntoPlane(Rotation.first);
450 newPosition.ProjectOntoPlane(Rotation.first);
451 LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition);
452 } else {
453 if (_bestmatching.size() == 2) {
454 // line situation
455 try {
456 Plane oldplane(oldPosition, oldCenter, newPosition);
457 Rotation.first = oldplane.getNormal();
458 LOG(6, "DEBUG: Plane is " << oldplane << " and normal is " << Rotation.first);
459 } catch (LinearDependenceException &e) {
460 LOG(6, "DEBUG: Vectors defining plane are linearly dependent.");
461 // oldPosition and newPosition are on a line, just flip when not equal
462 if (!oldPosition.IsEqualTo(newPosition)) {
463 Rotation.first.Zero();
464 Rotation.first.GetOneNormalVector(oldPosition);
465 LOG(6, "DEBUG: For flipping we use Rotation.first " << Rotation.first);
466 assert( Rotation.first.ScalarProduct(oldPosition) < std::numeric_limits<double>::epsilon()*1e4);
467 // Rotation.second = M_PI;
468 } else {
469 LOG(6, "DEBUG: oldPosition and newPosition are equivalent.");
470 }
471 }
472 } else {
473 // triangle situation
474 Plane oldplane(remainingold[0], remainingold[1], remainingold[2]);
475 Rotation.first = oldplane.getNormal();
476 LOG(6, "DEBUG: oldPlane is " << oldplane << " and normal is " << Rotation.first);
477 oldPosition.ProjectOntoPlane(Rotation.first);
478 LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition);
479 }
480 }
481 // construct reference vector to determine direction of rotation
482 const double sign = determineSignOfRotation(oldPosition, newPosition, Rotation.first);
483 Rotation.second = sign * oldPosition.Angle(newPosition);
484 } else {
485 LOG(6, "DEBUG: oldPosition and newPosition are equivalent, hence no orientating rotation.");
486 }
487
488 return Rotation;
489}
490
491
492SphericalPointDistribution::Polygon_t
493SphericalPointDistribution::matchSphericalPointDistributions(
494 const SphericalPointDistribution::WeightedPolygon_t &_polygon,
495 const SphericalPointDistribution::Polygon_t &_newpolygon
496 )
497{
498 SphericalPointDistribution::Polygon_t remainingpoints;
499 VectorArray_t remainingold;
500 for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
501 iter != _polygon.end(); ++iter)
502 remainingold.push_back(iter->first);
503 VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());
504 LOG(2, "INFO: Matching old polygon " << _polygon
505 << " with new polygon " << _newpolygon);
506
507 if (_polygon.size() == _newpolygon.size()) {
508 // same number of points desired as are present? Do nothing
509 LOG(2, "INFO: There are no vacant points to return.");
510 return remainingpoints;
511 }
512
513 if (_polygon.size() > 0) {
514 IndexList_t bestmatching = findBestMatching(_polygon, _newpolygon);
515 LOG(2, "INFO: Best matching is " << bestmatching);
516
517 // determine rotation angles to align the two point distributions with
518 // respect to bestmatching:
519 // we use the center between the three first matching points
520 /// the first rotation brings these two centers to coincide
521 VectorArray_t rotated_newpolygon = remainingnew;
522 {
523 Rotation_t Rotation = findPlaneAligningRotation(
524 remainingold,
525 remainingnew,
526 bestmatching);
527 LOG(5, "DEBUG: Rotating coordinate system by " << Rotation.second
528 << " around axis " << Rotation.first);
529 Line Axis(zeroVec, Rotation.first);
530
531 // apply rotation angle to bring newCenter to oldCenter
532 for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
533 iter != rotated_newpolygon.end(); ++iter) {
534 Vector &current = *iter;
535 LOG(6, "DEBUG: Original point is " << current);
536 current = Axis.rotateVector(current, Rotation.second);
537 LOG(6, "DEBUG: Rotated point is " << current);
538 }
539
540#ifndef NDEBUG
541 // check: rotated "newCenter" should now equal oldCenter
542 {
543 Vector oldCenter;
544 Vector rotatednewCenter;
545 calculateOldAndNewCenters(
546 oldCenter, rotatednewCenter,
547 remainingold, rotated_newpolygon, bestmatching);
548 // NOTE: Center must not necessarily lie on the sphere with norm 1, hence, we
549 // have to normalize it just as before, as oldCenter and newCenter lengths may differ.
550 if ((!oldCenter.IsZero()) && (!rotatednewCenter.IsZero())) {
551 oldCenter.Normalize();
552 rotatednewCenter.Normalize();
553 LOG(4, "CHECK: rotatednewCenter is " << rotatednewCenter
554 << ", oldCenter is " << oldCenter);
555 ASSERT( (rotatednewCenter - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4,
556 "matchSphericalPointDistributions() - rotation does not work as expected by "
557 +toString((rotatednewCenter - oldCenter).NormSquared())+".");
558 }
559 }
560#endif
561 }
562 /// the second (orientation) rotation aligns the planes such that the
563 /// points themselves coincide
564 if (bestmatching.size() > 1) {
565 Rotation_t Rotation = findPointAligningRotation(
566 remainingold,
567 rotated_newpolygon,
568 bestmatching);
569
570 // construct RotationAxis and two points on its plane, defining the angle
571 Rotation.first.Normalize();
572 const Line RotationAxis(zeroVec, Rotation.first);
573
574 LOG(5, "DEBUG: Rotating around self is " << Rotation.second
575 << " around axis " << RotationAxis);
576
577#ifndef NDEBUG
578 // check: first bestmatching in rotated_newpolygon and remainingnew
579 // should now equal
580 {
581 const IndexList_t::const_iterator iter = bestmatching.begin();
582 Vector rotatednew = RotationAxis.rotateVector(
583 rotated_newpolygon[*iter],
584 Rotation.second);
585 LOG(4, "CHECK: rotated first new bestmatching is " << rotatednew
586 << " while old was " << remainingold[0]);
587 ASSERT( (rotatednew - remainingold[0]).Norm() < warn_amplitude,
588 "matchSphericalPointDistributions() - orientation rotation ends up off by more than "
589 +toString(warn_amplitude)+".");
590 }
591#endif
592
593 for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
594 iter != rotated_newpolygon.end(); ++iter) {
595 Vector &current = *iter;
596 LOG(6, "DEBUG: Original point is " << current);
597 current = RotationAxis.rotateVector(current, Rotation.second);
598 LOG(6, "DEBUG: Rotated point is " << current);
599 }
600 }
601
602 // remove all points in matching and return remaining ones
603 SphericalPointDistribution::Polygon_t remainingpoints =
604 removeMatchingPoints(rotated_newpolygon, bestmatching);
605 LOG(2, "INFO: Remaining points are " << remainingpoints);
606 return remainingpoints;
607 } else
608 return _newpolygon;
609}
Note: See TracBrowser for help on using the repository browser.