source: src/Fragmentation/Exporters/SphericalPointDistribution.cpp@ 260540

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