NEST main@caf0ae8
 
Loading...
Searching...
No Matches
mask_impl.h
Go to the documentation of this file.
1/*
2 * mask_impl.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef MASK_IMPL_H
24#define MASK_IMPL_H
25
26#include "mask.h"
27
28namespace nest
29{
30
31template < int D >
32AbstractMask*
34{
35 const Mask* other_d = dynamic_cast< const Mask* >( &other );
36 if ( other_d == 0 )
37 {
38 throw BadProperty( "Masks must have same number of dimensions." );
39 }
40 return new IntersectionMask< D >( *this, *other_d );
41}
42
43template < int D >
46{
47 const Mask* other_d = dynamic_cast< const Mask* >( &other );
48 if ( other_d == 0 )
49 {
50 throw BadProperty( "Masks must have same number of dimensions." );
51 }
52 return new UnionMask< D >( *this, *other_d );
53}
54
55template < int D >
58{
59 const Mask* other_d = dynamic_cast< const Mask* >( &other );
60 if ( other_d == 0 )
61 {
62 throw BadProperty( "Masks must have same number of dimensions." );
63 }
64 return new DifferenceMask< D >( *this, *other_d );
65}
66
67template < int D >
68bool
69Mask< D >::inside( const std::vector< double >& pt ) const
70{
71 return inside( Position< D >( pt ) );
72}
73
74template < int D >
75bool
77{
78 Box< D > bb = get_bbox();
79 for ( int i = 0; i < D; ++i )
80 {
81 if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] )
82 {
83 return true;
84 }
85 }
86 return false;
87}
88
89template < int D >
90bool
92{
93 return ( inside( b.lower_left ) and inside( b.upper_right ) );
94}
95
96template < int D >
97bool
99{
100 // Note: There could be some inconsistencies with the boundaries. For the
101 // inside() function we had to add an epsilon because of rounding errors that
102 // can occur if node IDs are on the boundary if we have rotation. This might lead
103 // to overlap of the inside and outside functions. None of the tests have
104 // picked up any problems with this potential overlap as of yet (autumn 2017),
105 // so we don't know if it is an actual problem.
106 for ( int i = 0; i < D; ++i )
107 {
108 if ( b.upper_right[ i ] < min_values_[ i ] or b.lower_left[ i ] > max_values_[ i ] )
109 {
110 return true;
111 }
112 }
113 return false;
114}
115
116template < int D >
119{
120 return Box< D >( min_values_, max_values_ );
121}
122
123template < int D >
126{
127 return new BoxMask( *this );
128}
129
130template < int D >
133{
134 Dictionary d;
135 Dictionary maskd;
136 d[ get_name() ] = maskd;
137 maskd[ names::lower_left ] = lower_left_.get_vector();
138 maskd[ names::upper_right ] = upper_right_.get_vector();
139 maskd[ names::azimuth_angle ] = azimuth_angle_;
140 maskd[ names::polar_angle ] = polar_angle_;
141 return d;
142}
143
144template < int D >
145bool
147{
148 // Optimizing by trying to avoid expensive calculations.
149 double dim_sum = 0;
150 // First check each dimension
151 for ( int i = 0; i < D; ++i )
152 {
153 const double di = std::abs( p[ i ] - center_[ i ] );
154 if ( di > radius_ )
155 {
156 return false;
157 }
158 dim_sum += di;
159 }
160 // Next, check if we are inside a diamond (rotated square), which fits inside the ball.
161 if ( dim_sum <= radius_ )
162 {
163 return true;
164 }
165 // Point must be somewhere between the ball mask edge and the diamond edge,
166 // revert to expensive calculation in this case.
167 return ( p - center_ ).length() <= radius_;
168}
169
170template < int D >
171bool
173{
174 // Currently only checks if the box is outside the bounding box of
175 // the ball. This could be made more refined.
176 for ( int i = 0; i < D; ++i )
177 {
178 if ( b.upper_right[ i ] < center_[ i ] - radius_ or b.lower_left[ i ] > center_[ i ] + radius_ )
179 {
180 return true;
181 }
182 }
183 return false;
184}
185
186template < int D >
189{
190 Box< D > bb( center_, center_ );
191 for ( int i = 0; i < D; ++i )
192 {
193 bb.lower_left[ i ] -= radius_;
194 bb.upper_right[ i ] += radius_;
195 }
196 return bb;
197}
198
199template < int D >
202{
203 return new BallMask( *this );
204}
205
206template < int D >
209{
210 Dictionary d;
211 Dictionary maskd;
212 maskd[ names::radius ] = radius_;
213 maskd[ names::anchor ] = center_.get_vector();
214 d[ get_name() ] = maskd;
215 return d;
216}
217
218template < int D >
219void
221{
222 // Currently assumes 3D when constructing the radius vector. This could be
223 // avoided with more if tests, but the vector is only made once and is not
224 // big. The construction of the box is done in accordance with the actual
225 // dimensions.
226 std::vector< double > radii( 3 );
227 if ( azimuth_angle_ == 0.0 and polar_angle_ == 0.0 )
228 {
229 radii[ 0 ] = major_axis_ / 2.0;
230 radii[ 1 ] = minor_axis_ / 2.0;
231 radii[ 2 ] = polar_axis_ / 2.0;
232 }
233 else
234 {
235 // If the ellipse or ellipsoid is tilted, we make the boundary box
236 // quadratic, with the length of the sides equal to the axis with greatest
237 // length. This could be more refined.
238 const double greatest_semi_axis = std::max( major_axis_, polar_axis_ ) / 2.0;
239 radii[ 0 ] = greatest_semi_axis;
240 radii[ 1 ] = greatest_semi_axis;
241 radii[ 2 ] = greatest_semi_axis;
242 }
243
244 for ( int i = 0; i < D; ++i )
245 {
246 bbox_.lower_left[ i ] = center_[ i ] - radii[ i ];
247 bbox_.upper_right[ i ] = center_[ i ] + radii[ i ];
248 }
249}
250
251template < int D >
252bool
254{
255 // Currently only checks if the box is outside the bounding box of
256 // the ellipse. This could be made more refined.
257
258 const Box< D >& bb = bbox_;
259
260 for ( int i = 0; i < D; ++i )
261 {
262 if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] )
263 {
264 return true;
265 }
266 }
267 return false;
268}
269
270template < int D >
273{
274 return bbox_;
275}
276
277template < int D >
280{
281 return new EllipseMask( *this );
282}
283
284template < int D >
287{
288 Dictionary d;
289 Dictionary maskd;
290 maskd[ names::major_axis ] = major_axis_;
291 maskd[ names::minor_axis ] = minor_axis_;
292 maskd[ names::polar_axis ] = polar_axis_;
293 maskd[ names::anchor ] = center_.get_vector();
294 maskd[ names::azimuth_angle ] = azimuth_angle_;
295 maskd[ names::polar_angle ] = polar_angle_;
296 d[ get_name() ] = maskd;
297 return d;
298}
299
300
301template < int D >
302bool
304{
305 return mask1_->inside( p ) and mask2_->inside( p );
306}
307
308template < int D >
309bool
311{
312 return mask1_->inside( b ) and mask2_->inside( b );
313}
314
315template < int D >
316bool
318{
319 return mask1_->outside( b ) or mask2_->outside( b );
320}
321
322template < int D >
325{
326 Box< D > bb = mask1_->get_bbox();
327 Box< D > bb2 = mask2_->get_bbox();
328 for ( int i = 0; i < D; ++i )
329 {
330 if ( bb2.lower_left[ i ] > bb.lower_left[ i ] )
331 {
332 bb.lower_left[ i ] = bb2.lower_left[ i ];
333 }
334 if ( bb2.upper_right[ i ] < bb.upper_right[ i ] )
335 {
336 bb.upper_right[ i ] = bb2.upper_right[ i ];
337 }
338 }
339 return bb;
340}
341
342template < int D >
345{
346 return new IntersectionMask( *this );
347}
348
349template < int D >
350bool
352{
353 return mask1_->inside( p ) or mask2_->inside( p );
354}
355
356template < int D >
357bool
359{
360 return mask1_->inside( b ) or mask2_->inside( b );
361}
362
363template < int D >
364bool
366{
367 return mask1_->outside( b ) and mask2_->outside( b );
368}
369
370template < int D >
373{
374 Box< D > bb = mask1_->get_bbox();
375 Box< D > bb2 = mask2_->get_bbox();
376 for ( int i = 0; i < D; ++i )
377 {
378 if ( bb2.lower_left[ i ] < bb.lower_left[ i ] )
379 {
380 bb.lower_left[ i ] = bb2.lower_left[ i ];
381 }
382 if ( bb2.upper_right[ i ] > bb.upper_right[ i ] )
383 {
384 bb.upper_right[ i ] = bb2.upper_right[ i ];
385 }
386 }
387 return bb;
388}
389
390template < int D >
393{
394 return new UnionMask( *this );
395}
396
397template < int D >
398bool
400{
401 return mask1_->inside( p ) and not mask2_->inside( p );
402}
403
404template < int D >
405bool
407{
408 return mask1_->inside( b ) and mask2_->outside( b );
409}
410
411template < int D >
412bool
414{
415 return mask1_->outside( b ) or mask2_->inside( b );
416}
417
418template < int D >
421{
422 return mask1_->get_bbox();
423}
424
425template < int D >
428{
429 return new DifferenceMask( *this );
430}
431
432template < int D >
433bool
435{
436 return m_->inside( -p );
437}
438
439template < int D >
440bool
442{
443 return m_->inside( Box< D >( -b.upper_right, -b.lower_left ) );
444}
445
446template < int D >
447bool
449{
450 return m_->outside( Box< D >( -b.upper_right, -b.lower_left ) );
451}
452
453template < int D >
456{
457 Box< D > bb = m_->get_bbox();
458 return Box< D >( -bb.upper_right, -bb.lower_left );
459}
460
461template < int D >
464{
465 return new ConverseMask( *this );
466}
467
468template < int D >
469bool
471{
472 return m_->inside( p - anchor_ );
473}
474
475template < int D >
476bool
478{
479 return m_->inside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) );
480}
481
482template < int D >
483bool
485{
486 return m_->outside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) );
487}
488
489template < int D >
492{
493 Box< D > bb = m_->get_bbox();
494 return Box< D >( bb.lower_left + anchor_, bb.upper_right + anchor_ );
495}
496
497template < int D >
500{
501 return new AnchoredMask( *this );
502}
503
504template < int D >
507{
508 Dictionary d = m_->get_dict();
509 d[ names::anchor ] = anchor_.get_vector();
510 return d;
511}
512
513} // namespace nest
514
515#endif
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
Abstract base class for masks with unspecified dimension.
Definition mask.h:51
Mask shifted by an anchor.
Definition mask.h:677
bool outside(const Box< D > &b) const
Definition mask_impl.h:484
Box< D > get_bbox() const
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:491
bool inside(const Position< D > &p) const
Definition mask_impl.h:470
Mask< D > * clone() const
Clone method.
Definition mask_impl.h:499
Dictionary get_dict() const
Definition mask_impl.h:506
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition exceptions.h:680
Mask defining a circular or spherical region.
Definition mask.h:308
Dictionary get_dict() const override
Definition mask_impl.h:208
bool outside(const Box< D > &b) const override
Definition mask_impl.h:172
bool inside(const Position< D > &p) const override
Definition mask_impl.h:146
Mask< D > * clone() const override
Clone method.
Definition mask_impl.h:201
Box< D > get_bbox() const override
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:188
Mask defining a box region.
Definition mask.h:209
bool outside(const Box< D > &b) const override
Definition mask_impl.h:98
Box< D > get_bbox() const override
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:118
bool inside(const Position< D > &p) const override
Dictionary get_dict() const override
Definition mask_impl.h:132
Mask< D > * clone() const override
Clone method.
Definition mask_impl.h:125
Mask oriented in the opposite direction.
Definition mask.h:633
Box< D > get_bbox() const
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:455
bool inside(const Position< D > &p) const
Definition mask_impl.h:434
Mask< D > * clone() const
Clone method.
Definition mask_impl.h:463
bool outside(const Box< D > &b) const
Definition mask_impl.h:448
Mask combining two masks with a minus operation, the difference.
Definition mask.h:586
Box< D > get_bbox() const
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:420
Mask< D > * clone() const
Clone method.
Definition mask_impl.h:427
bool outside(const Box< D > &b) const
Definition mask_impl.h:413
bool inside(const Position< D > &p) const
Definition mask_impl.h:399
Mask defining an elliptical or ellipsoidal region.
Definition mask.h:369
void create_bbox_()
Definition mask_impl.h:220
Mask< D > * clone() const override
Clone method.
Definition mask_impl.h:279
Dictionary get_dict() const override
Definition mask_impl.h:286
Box< D > get_bbox() const override
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:272
bool outside(const Box< D > &b) const override
Definition mask_impl.h:253
Mask combining two masks with a Boolean AND, the intersection.
Definition mask.h:491
Box< D > get_bbox() const
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:324
Mask< D > * clone() const
Clone method.
Definition mask_impl.h:344
bool outside(const Box< D > &b) const
Definition mask_impl.h:317
bool inside(const Position< D > &p) const
Definition mask_impl.h:303
Abstract base class for masks with given dimension.
Definition mask.h:101
AbstractMask * intersect_mask(const AbstractMask &other) const override
Create the intersection of this mask with another.
Definition mask_impl.h:33
virtual bool inside(const Position< D > &) const =0
virtual bool outside(const Box< D > &b) const
Definition mask_impl.h:76
AbstractMask * minus_mask(const AbstractMask &other) const override
Create the difference of this mask and another.
Definition mask_impl.h:57
AbstractMask * union_mask(const AbstractMask &other) const override
Create the union of this mask with another.
Definition mask_impl.h:45
Definition position.h:57
Mask combining two masks with a Boolean OR, the sum.
Definition mask.h:540
bool inside(const Position< D > &p) const
Definition mask_impl.h:351
Box< D > get_bbox() const
The whole mask is inside (i.e., false everywhere outside) the bounding box.
Definition mask_impl.h:372
bool outside(const Box< D > &b) const
Definition mask_impl.h:365
Mask< D > * clone() const
Clone method.
Definition mask_impl.h:392
const std::string polar_axis("polar_axis")
const std::string polar_angle("polar_angle")
const std::string anchor("anchor")
const std::string azimuth_angle("azimuth_angle")
const std::string minor_axis("minor_axis")
const std::string radius("radius")
const std::string major_axis("major_axis")
const std::string lower_left("lower_left")
const std::string upper_right("upper_right")
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
bool inside(const std::vector< double > &point, const MaskPTR mask)
Definition spatial.cpp:499
A box is defined by the lower left corner (minimum coordinates) and the upper right corner (maximum c...
Definition position.h:321
Position< D > lower_left
Definition position.h:331
Position< D > upper_right
Definition position.h:332