Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BumpGrid.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 // :noTabs=false:tabSize=4:indentSize=4:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file protocols/match/BumpGrid.cc
12 /// @brief
13 /// @author Alex Zanghellini (zanghell@u.washington.edu)
14 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com), porting to mini
15 
16 
17 #include <protocols/match/BumpGrid.hh> // typedefs for Bin3D.
18 
23 #include <core/pose/Pose.hh>
24 
25 #include <basic/Tracer.hh>
26 
27 #include <utility/vector1.hh>
28 
29 
30 namespace protocols {
31 namespace match {
32 
33 static basic::Tracer TR( "protocols.BumpGrid" );
34 
35 /// Creation and initialization
37  bb_( Vector(0.0) ),
38  bb_extended_( Vector(0.0) ),
39  bin_width_( 1.0 ),
40  bin_width_2x_( 2.0 ),
41  dimsizes_( 0 ),
42  dimprods_( 0 ),
43  halfdimsizes_( 0 ),
44  halfdimprods_( 0 )
45 {}
46 
48 
49 void
51  bb_ = bb;
52  reset_grid();
53 }
54 
56  bin_width_ = width;
57  reset_grid();
58 }
59 
61 Bool3DGrid::create_grid_for_sphere( Vector const & center, Real radius ) const
62 {
63  Bool3DGrid newgrid;
64  newgrid.set_bin_width( bin_width_ );
65 
66  /// Make the axes ling up with this grid.
67  Vector local_center = center - bb_.lower();
68  Vector low_corner = local_center - radius;
69 
70  assert( low_corner.x() >= 0.0 && low_corner.y() >= 0.0 && low_corner.z() >= 0.0 );
71 
72  Bin3D halfgrid_of_lowcorner;
73  halfgrid_of_lowcorner[ 1 ] = static_cast< Size > ( low_corner.x() / ( 2 * bin_width_ ) );
74  halfgrid_of_lowcorner[ 2 ] = static_cast< Size > ( low_corner.y() / ( 2 * bin_width_ ) );
75  halfgrid_of_lowcorner[ 3 ] = static_cast< Size > ( low_corner.z() / ( 2 * bin_width_ ) );
76 
77  Vector aligned_low_corner( bb_.lower() );
78  aligned_low_corner.x() += bin_width_2x_ * halfgrid_of_lowcorner[ 1 ];
79  aligned_low_corner.y() += bin_width_2x_ * halfgrid_of_lowcorner[ 2 ];
80  aligned_low_corner.z() += bin_width_2x_ * halfgrid_of_lowcorner[ 3 ];
81 
82  Vector upper_corner = local_center + radius;
83  newgrid.set_bounding_box( BoundingBox( aligned_low_corner, upper_corner ) );
84  return newgrid;
85 }
86 
87 /// @brief create a grid for the input bounding box that aligns to this grid
90 {
91  Bool3DGrid newgrid;
92  newgrid.set_bin_width( bin_width_ );
93 
94  /// Make the axes line up with this grid.
95  Vector local_center = bb.lower() - bb_.lower();
96 
97  utility::fixedsizearray1< int, 3 > floored_lower;
98  floored_lower[ 1 ] = static_cast< Size > ( local_center.x() / bin_width_ );
99  floored_lower[ 2 ] = static_cast< Size > ( local_center.y() / bin_width_ );
100  floored_lower[ 3 ] = static_cast< Size > ( local_center.z() / bin_width_ );
101 
102  Vector aligned_lower(
103  bb_.lower().x() + floored_lower[ 1 ] * bin_width_,
104  bb_.lower().y() + floored_lower[ 2 ] * bin_width_,
105  bb_.lower().z() + floored_lower[ 3 ] * bin_width_ );
106 
107  newgrid.set_bounding_box( BoundingBox( aligned_lower, bb.upper() ) );
108  return newgrid;
109 }
110 
111 
112 /// @details Sets the value of a voxel to true if all eight corners
113 /// of the voxel are contained by the sphere.
114 void
116 {
117  using namespace core;
118 
119  Real const rad2 = radius * radius;
120  Real const rad_minus_cendis = radius - half_bin_width_root_three_;
121 
122  /// If the radius is so small that no voxel could be completly covered by a sphere,
123  /// then find the handful of voxels that might be overlapped by this tiny sphere,
124  /// and process them separately than if rad_minus_cendis were positive.
125  if ( rad_minus_cendis < 0 ) {
126  /// unimplemented at the moment.
127  return;
128  }
129 
130  Real rad_minus_cendis2 = rad_minus_cendis * rad_minus_cendis;
131  Real const rad_plus_cendis = half_bin_width_root_three_ + radius;
132  Real const rad_plus_cendis2 = rad_plus_cendis * rad_plus_cendis;
133 
134  Bin3D bin;
135 
136  Vector relpos = center - bb_extended_.lower();
137  SSize xlo( static_cast< SSize > ((relpos.x() - radius) / bin_width_ ));
138  SSize xhi( static_cast< SSize > ((relpos.x() + radius) / bin_width_ ) + 1);
139  SSize ylo( static_cast< SSize > ((relpos.y() - radius) / bin_width_ ));
140  SSize yhi( static_cast< SSize > ((relpos.y() + radius) / bin_width_ ) + 1);
141  SSize zlo( static_cast< SSize > ((relpos.z() - radius) / bin_width_ ));
142  SSize zhi( static_cast< SSize > ((relpos.z() + radius) / bin_width_ ) + 1);
143 
144  Size uxlo = xlo < 0 ? 0 : xlo;
145  Size uxhi = xhi < 0 ? 0 : ( xhi > SSize( dimsizes_[ 1 ] ) ? dimsizes_[ 1 ] : xhi ) ;
146  Size uylo = ylo < 0 ? 0 : ylo;
147  Size uyhi = yhi < 0 ? 0 : ( yhi > SSize( dimsizes_[ 2 ] ) ? dimsizes_[ 2 ] : yhi ) ;
148  Size uzlo = zlo < 0 ? 0 : zlo;
149  Size uzhi = zhi < 0 ? 0 : ( zhi > SSize( dimsizes_[ 3 ] ) ? dimsizes_[ 3 ] : zhi ) ;
150 
151  for ( Size ii = uxlo; ii < uxhi; ++ii ) {
152  bin[ 1 ] = ii;
153  for ( Size jj = uylo; jj < uyhi; ++jj ) {
154  bin[ 2 ] = jj;
155  for ( Size kk = uzlo; kk < uzhi; ++kk ) {
156  bin[ 3 ] = kk;
157 
158  Vector bin_center_point( bin_center( bin ));
159  Real sphere_cent_to_voxel_cent2 = bin_center_point.distance_squared( center );
160  if ( sphere_cent_to_voxel_cent2 > rad_plus_cendis2 ) continue;
161 
162  bool all_contained( true );
163  if ( sphere_cent_to_voxel_cent2 > rad_minus_cendis2 ) { // Only look at all the corners if it's possible not all corners are covered by the sphere.
164  utility::fixedsizearray1< Vector, 8 > grid_corners = corners( bin );
165  for ( Size ll = 1; ll <= 8; ++ll ) {
166  Real d2 = center.distance_squared( grid_corners[ ll ] );
167  if ( d2 > rad2 ) { all_contained = false; break; }
168  }
169  }
170  if ( all_contained ) {
171  set_value_for_bin( bin, true );
172  }
173  }
174  }
175  }
176 
177 }
178 
179 /// @details Sets the value of a voxel to true if any volume of a voxel is inside
180 /// the sphere. Handles edge cases properly where a voxel is glanced by a sphere
181 /// at a face, but where the corners of the voxel are not contained by the sphere,
182 /// and when a sphere is entirely contained within a voxel.
183 void
185 {
186 /* Real rad2 = radius * radius;
187  Bin3D bin;
188  for ( Size ii = 0; ii < dimsizes_[ 1 ]; ++ii ) {
189  bin[ 1 ] = ii;
190  for ( Size jj = 0; jj < dimsizes_[ 2 ]; ++jj ) {
191  bin[ 2 ] = jj;
192  for ( Size kk = 0; kk < dimsizes_[ 3 ]; ++kk ) {
193  bin[ 3 ] = kk;
194  utility::fixedsizearray1< Vector, 8 > grid_corners = corners( bin );
195  bool any_contained( false );
196  for ( Size ll = 1; ll <= 8; ++ll ) {
197  Real d2 = center.distance_squared( grid_corners[ ll ] );
198  if ( d2 <= rad2 ) { any_contained = true; break; }
199  }
200  if ( any_contained ) {
201  set_value_for_bin( bin, true );
202  }
203  }
204  }
205  }
206 */
207 
208  using namespace core;
209 
210  Real const rad2 = radius * radius;
211  Real const rad_minus_cendis = radius - half_bin_width_root_three_;
212 
213  Real rad_minus_cendis2 = rad_minus_cendis * rad_minus_cendis;
214  Real const rad_plus_cendis = half_bin_width_root_three_ + radius;
215  Real const rad_plus_cendis2 = rad_plus_cendis * rad_plus_cendis;
216 
217  Bin3D bin;
218  Vector relpos = center - bb_extended_.lower();
219  SSize xlo( static_cast< SSize > ((relpos.x() - radius) / bin_width_ ));
220  SSize xhi( static_cast< SSize > ((relpos.x() + radius) / bin_width_ ) + 1);
221  SSize ylo( static_cast< SSize > ((relpos.y() - radius) / bin_width_ ));
222  SSize yhi( static_cast< SSize > ((relpos.y() + radius) / bin_width_ ) + 1);
223  SSize zlo( static_cast< SSize > ((relpos.z() - radius) / bin_width_ ));
224  SSize zhi( static_cast< SSize > ((relpos.z() + radius) / bin_width_ ) + 1);
225 
226  Size uxlo = xlo < 0 ? 0 : xlo;
227  Size uxhi = xhi < 0 ? 0 : ( xhi > SSize( dimsizes_[ 1 ] ) ? dimsizes_[ 1 ] : xhi ) ;
228  Size uylo = ylo < 0 ? 0 : ylo;
229  Size uyhi = yhi < 0 ? 0 : ( yhi > SSize( dimsizes_[ 2 ] ) ? dimsizes_[ 2 ] : yhi ) ;
230  Size uzlo = zlo < 0 ? 0 : zlo;
231  Size uzhi = zhi < 0 ? 0 : ( zhi > SSize( dimsizes_[ 3 ] ) ? dimsizes_[ 3 ] : zhi ) ;
232 
233  for ( Size ii = uxlo; ii < uxhi; ++ii ) {
234  bin[ 1 ] = ii;
235  for ( Size jj = uylo; jj < uyhi; ++jj ) {
236  bin[ 2 ] = jj;
237  for ( Size kk = uzlo; kk < uzhi; ++kk ) {
238  bin[ 3 ] = kk;
239 
240  Vector bin_center_point( bin_center( bin ));
241  Real sphere_cent_to_voxel_cent2 = bin_center_point.distance_squared( center );
242 
243  /// If the distance between the sphere center and the voxel center is greater
244  /// than the radius of the sphere plus the distance from the voxel center and
245  /// one of it's corners, then it is impossible for any part of this voxel to
246  /// overlap with the sphere. Proceed to the next voxel.
247  if ( sphere_cent_to_voxel_cent2 > rad_plus_cendis2 ) continue;
248 
249  /// if the voxel center is contained within the sphere, mark this voxel as occupied and move on.
250  bool any_contained( sphere_cent_to_voxel_cent2 < rad2 );
251 
252  if ( !any_contained && sphere_cent_to_voxel_cent2 > rad_minus_cendis2 ) {
253  // Possible that some corners are covered by the sphere, but not guaranteed.
254  utility::fixedsizearray1< Vector, 8 > grid_corners = corners( bin );
255  for ( Size ll = 1; ll <= 8; ++ll ) {
256  Real d2 = center.distance_squared( grid_corners[ ll ] );
257  if ( d2 < rad2 ) { any_contained = true; break; }
258  }
259  if ( ! any_contained ) {
260  /// look for a glancing contact between a sphere and one face of this box,
261  /// or containment of the sphere within the box
262  bool x_in_range = ( center.x() >= grid_corners[ 1 ].x() && center.x() <= grid_corners[ 8 ].x() );
263  bool y_in_range = ( center.y() >= grid_corners[ 1 ].y() && center.y() <= grid_corners[ 8 ].y() );
264  bool z_in_range = ( center.z() >= grid_corners[ 1 ].z() && center.z() <= grid_corners[ 8 ].z() );
265  Size n_in_range = (Size) x_in_range + ( Size ) y_in_range + ( Size ) z_in_range;
266 
267  if ( n_in_range == 2 ) {
268  /// glancing contact possible. Distance from sphere center to the voxel face is
269  /// the distance along the dimension that's not in range.
270  Size dim_out_of_range( 1 );
271  if ( ! x_in_range ) {
272  dim_out_of_range = 1;
273  } else if ( ! y_in_range ) {
274  dim_out_of_range = 2;
275  } else { //if ( ! z_in_range ) {
276  assert( ! z_in_range );
277  dim_out_of_range = 3;
278  }
279 
280  Real dim_edge;
281  if ( center( dim_out_of_range ) < grid_corners[ 1 ]( dim_out_of_range )) {
282  dim_edge = grid_corners[ 1 ]( dim_out_of_range );
283  } else {
284  dim_edge = grid_corners[ 8 ]( dim_out_of_range );
285  }
286  Real d = center( dim_out_of_range ) - dim_edge;
287  if ( d*d < rad2 ) {
288  any_contained = true;
289  }
290  }
291  }
292  }
293 
294  if ( any_contained ) {
295  set_value_for_bin( bin, true );
296  }
297  }
298  }
299  }
300 
301 }
302 
303 /// @details The sphere list should describe spheres by the centers and by their
304 /// square radii, not by their radii.
305 void
307  utility::vector1< std::pair< Vector, Real > > const & spheres
308 )
309 {
310  Bin3D bin;
311  for ( Size ii = 0; ii < dimsizes_[ 1 ]; ++ii ) {
312  bin[ 1 ] = ii;
313  for ( Size jj = 0; jj < dimsizes_[ 2 ]; ++jj ) {
314  bin[ 2 ] = jj;
315  for ( Size kk = 0; kk < dimsizes_[ 3 ]; ++kk ) {
316  bin[ 3 ] = kk;
317  CornerPoints grid_corners = corners( bin );
318  bool all_corners_contained( true );
319  for ( Size ll = 1; ll <= 8; ++ll ) {
320  bool contained_anywhere( false );
321  for ( Size mm = 1; mm <= spheres.size(); ++mm ) {
322  Real d2 = spheres[ mm ].first.distance_squared( grid_corners[ ll ] );
323  if ( d2 <= spheres[ mm ].second ) { contained_anywhere = true; break; }
324  }
325  if ( ! contained_anywhere ) {
326  all_corners_contained = false;
327  break;
328  }
329  }
330  if ( all_corners_contained ) {
331  set_value_for_bin( bin, true );
332  }
333  }
334  }
335  }
336 
337 }
338 
339 //// @brief Turn the values of all the bins that overlap with the
340 /// volume in this bounding box to true.
341 void
343  BoundingBox const & bb
344 )
345 {
346  Vector clipped_lower( bb.lower() ), clipped_upper( bb.upper() );
347  for ( Size ii = 1; ii <= 3; ++ii ) if ( clipped_lower( ii ) < bb_.lower()( ii ) ) clipped_lower( ii ) = bb_.lower()( ii );
348  for ( Size ii = 1; ii <= 3; ++ii ) if ( clipped_upper( ii ) > bb_.upper()( ii ) ) clipped_upper( ii ) = bb_.upper()( ii );
349 
350  Bin3D const bin_lo = bin_for_point( clipped_lower );
351  Bin3D const bin_hi = bin_for_point( clipped_upper );
352 
353  Bin3D bin;
354  for ( Size ii = bin_lo[ 1 ]; ii <= bin_hi[ 1 ]; ++ii ) {
355  bin[ 1 ] = ii;
356  for ( Size jj = bin_lo[ 2 ]; jj <= bin_hi[ 2 ]; ++jj ) {
357  bin[ 2 ] = jj;
358  for ( Size kk = bin_lo[ 3 ]; kk <= bin_hi[ 3 ]; ++kk ) {
359  bin[ 3 ] = kk;
360  set_value_for_bin( bin, true );
361  }
362  }
363  }
364 }
365 
366 /// Accessors
368  return dimsizes_;
369 }
370 
372 Bool3DGrid::corners( Bin3D const & bin ) const {
373  CornerPoints corns;
374  Vector lower_corner = bb_.lower();
375  lower_corner.x() += bin_width_ * bin[ 1 ];
376  lower_corner.y() += bin_width_ * bin[ 2 ];
377  lower_corner.z() += bin_width_ * bin[ 3 ];
378 
379  //corns[ 1 ] = lower_corner;
380  //corns[ 2 ] = lower_corner + bin_width_ * Vector( 0, 0, 1 );
381  //corns[ 3 ] = lower_corner + bin_width_ * Vector( 0, 1, 0 );
382  //corns[ 4 ] = lower_corner + bin_width_ * Vector( 0, 1, 1 );
383  //corns[ 5 ] = lower_corner + bin_width_ * Vector( 1, 0, 0 );
384  //corns[ 6 ] = lower_corner + bin_width_ * Vector( 1, 0, 1 );
385  //corns[ 7 ] = lower_corner + bin_width_ * Vector( 1, 1, 0 );
386  //corns[ 8 ] = lower_corner + bin_width_ * Vector( 1, 1, 1 );
387 
388  Real const xlo( lower_corner.x() ), xhi( lower_corner.x() + bin_width_ );
389  Real const ylo( lower_corner.y() ), yhi( lower_corner.y() + bin_width_ );
390  Real const zlo( lower_corner.z() ), zhi( lower_corner.z() + bin_width_ );
391 
392  corns[ 1 ] = Vector( xlo, ylo, zlo );
393  corns[ 2 ] = Vector( xlo, ylo, zhi );
394  corns[ 3 ] = Vector( xlo, yhi, zlo );
395  corns[ 4 ] = Vector( xlo, yhi, zhi );
396  corns[ 5 ] = Vector( xhi, ylo, zlo );
397  corns[ 6 ] = Vector( xhi, ylo, zhi );
398  corns[ 7 ] = Vector( xhi, yhi, zlo );
399  corns[ 8 ] = Vector( xhi, yhi, zhi );
400 
401 
402  //corns[ 1 ] = lower_corner;
403  //corns[ 2 ] = lower_corner; corns[ 2 ].z() += bin_width_; // Vector( 0, 0, 1 );
404  //corns[ 3 ] = lower_corner; corns[ 3 ].y() += bin_width_; // Vector( 0, 1, 0 );
405  //corns[ 4 ] = lower_corner; corns[ 4 ].y() += bin_width_; corns[ 4 ].z() += bin_width_; // Vector( 0, 1, 1 );
406  //corns[ 5 ] = lower_corner; corns[ 5 ].x() += bin_width_; // Vector( 1, 0, 0 );
407  //corns[ 6 ] = corns[ 5 ]; corns[ 6 ].z() += bin_width_; // Vector( 1, 0, 1 );
408  //corns[ 7 ] = corns[ 5 ]; corns[ 7 ].y() += bin_width_; // Vector( 1, 1, 0 );
409  //corns[ 8 ] = corns[ 5 ]; corns[ 8 ].y() += bin_width_; corns[ 8 ].z() += bin_width_;// Vector( 1, 1, 1 );
410 
411  return corns;
412 }
413 
415 Bool3DGrid::bin_extrema( Bin3D const & bin ) const
416 {
417  Vector lower_corner = bb_.lower();
418  lower_corner.x() += bin_width_ * bin[ 1 ];
419  lower_corner.y() += bin_width_ * bin[ 2 ];
420  lower_corner.z() += bin_width_ * bin[ 3 ];
421 
422  Vector upper_corner = lower_corner + bin_width_;
423 
424  return BoundingBox( lower_corner, upper_corner );
425 }
426 
428 Bool3DGrid::bin_center( Bin3D const & bin ) const {
429 
430  return Vector(
431  bin_width_ * bin[ 1 ] + bin_width_ / 2 ,
432  bin_width_ * bin[ 2 ] + bin_width_ / 2 ,
433  bin_width_ * bin[ 3 ] + bin_width_ / 2 ) + bb_extended_.lower();
434 }
435 
436 bool Bool3DGrid::occupied( Vector const & point ) const
437 {
438  if ( ! bb_extended_.contains( point ) ) return false;
439 
441  //std::cout << "occupied?: " << imp.first << " " << (int) grid_[ imp.first ] << " " << (int) imp.second << std::endl;
442  return grid_[ imp.first ] & imp.second;
443 }
444 
445 bool Bool3DGrid::occupied( Bin3D const & bin ) const
446 {
447  for ( Size ii = 1; ii <= 3; ++ii ) {
448  if ( bin[ ii ] >= dimsizes_[ ii ] ) return false;
449  }
450 
452  //std::cout << "occupied?: " << imp.first << " " << (int) grid_[ imp.first ] << " " << (int) imp.second << std::endl;
453  return grid_[ imp.first ] & imp.second;
454 
455 }
456 
457 // Mutators
458 void Bool3DGrid::set_value_for_bin( Bin3D const & bin, bool setting )
459 {
460  //std::cout << "setting value for bin " << bin[ 1 ] << " " << bin[ 2 ] << " " << bin[ 3 ] << " = " << setting << std::endl;
461 
462  Bin3D halfbin;
463  halfbin[ 1 ] = bin[ 1 ] / 2; Size xmod2 = bin[ 1 ] % 2;
464  halfbin[ 2 ] = bin[ 2 ] / 2; Size ymod2 = bin[ 2 ] % 2;
465  halfbin[ 3 ] = bin[ 3 ] / 2; Size zmod2 = bin[ 3 ] % 2;
466 
467  Size index = byte_index_from_doublebin( halfbin );
468  unsigned char & voxel_bits( grid_[ index ] );
469 
470  //unsigned char original_bits( grid_[ index ] ); /// for debugging -- commented out code below.
471 
472 
473  if ( setting ) {
474  // change only the value of the bit in question
475  unsigned char voxbit = mask_from_offsets( xmod2, ymod2, zmod2 );
476  voxel_bits |= voxbit;
477  } else {
478  // keep everything in the voxel bit in it's current state, except the bit in question
479  unsigned char mask = negmask_from_offsets( xmod2, ymod2, zmod2 );
480  voxel_bits &= mask;
481  }
482 
483  /*std::cout << "Setting " << setting << " for bin " << bin[ 1 ] << " " << bin[ 2 ] << " " << bin[ 3 ] << " (index " << index << ")";
484  std::cout << " with offset " << xmod2 << " " << ymod2 << " " << zmod2 << " original: ";
485  for ( Size ii = 0; ii <= 1; ++ii ) {
486  for ( Size jj = 0; jj <= 1; ++jj ) {
487  for ( Size kk = 0; kk <= 1; ++kk ) {
488  std::cout << ( mask_from_offsets( ii, jj, kk ) & original_bits ? 1 : 0 );
489  }
490  }
491  }
492  std::cout << " becomes ";
493  for ( Size ii = 0; ii <= 1; ++ii ) {
494  for ( Size jj = 0; jj <= 1; ++jj ) {
495  for ( Size kk = 0; kk <= 1; ++kk ) {
496  std::cout << ( mask_from_offsets( ii, jj, kk ) & voxel_bits ? 1 : 0 );
497  }
498  }
499  }
500  std::cout << std::endl;*/
501 }
502 
503 void Bool3DGrid::or_with( Bool3DGrid const & other )
504 {
505  assert( bin_width_ == other.bin_width_ );
506 
507  /// 1. Compute the bin overlap
508  Vector overlap_low(
509  std::max( bb_.lower().x(), other.bb_.lower().x() ),
510  std::max( bb_.lower().y(), other.bb_.lower().y() ),
511  std::max( bb_.lower().z(), other.bb_.lower().z() ) );
512 
513  Vector overlap_high(
514  std::min( bb_.upper().x(), other.bb_.upper().x() ),
515  std::min( bb_.upper().y(), other.bb_.upper().y() ),
516  std::min( bb_.upper().z(), other.bb_.upper().z() ) );
517 
518  /// Check for a situation in which the grids have no overlap.
519  if ( overlap_low.x() >= overlap_high.x() ||
520  overlap_low.y() >= overlap_high.y() ||
521  overlap_low.z() >= overlap_high.z() ) return;
522 
523  /// Assert that the two grids are compatible: that the region of overlap perfectly
524  /// contains all the voxels inside of it (no voxels spill out).
525  assert( std::abs( (overlap_low.x() - bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - bb_.lower().x()) / bin_width_ )) < 1e-6 );
526  assert( std::abs( (overlap_low.y() - bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - bb_.lower().y()) / bin_width_ )) < 1e-6 );
527  assert( std::abs( (overlap_low.z() - bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - bb_.lower().z()) / bin_width_ )) < 1e-6 );
528 
529  assert( std::abs( (overlap_low.x() - other.bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - other.bb_.lower().x()) / bin_width_ )) < 1e-6 );
530  assert( std::abs( (overlap_low.y() - other.bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - other.bb_.lower().y()) / bin_width_ )) < 1e-6 );
531  assert( std::abs( (overlap_low.z() - other.bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - other.bb_.lower().z()) / bin_width_ )) < 1e-6 );
532 
533  /// Iterate over the grid indices of this and other in the overlapping region.
534  Bin3D n_overlap;
535  Real const perturb = bin_width_ / 2;
536  n_overlap[ 1 ] = static_cast< Size > (( overlap_high.x() - overlap_low.x() + perturb ) / bin_width_ );
537  n_overlap[ 2 ] = static_cast< Size > (( overlap_high.y() - overlap_low.y() + perturb ) / bin_width_ );
538  n_overlap[ 3 ] = static_cast< Size > (( overlap_high.z() - overlap_low.z() + perturb ) / bin_width_ );
539 
540  Bin3D my_grid_start;
541  my_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - bb_.lower().x() + perturb ) / bin_width_ );
542  my_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - bb_.lower().y() + perturb ) / bin_width_ );
543  my_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - bb_.lower().z() + perturb ) / bin_width_ );
544 
545  Bin3D other_grid_start;
546  other_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - other.bb_.lower().x() + perturb ) / bin_width_ );
547  other_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - other.bb_.lower().y() + perturb ) / bin_width_ );
548  other_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - other.bb_.lower().z() + perturb ) / bin_width_ );
549 
550  Bin3D my_pos;
551  Bin3D other_pos;
552 
553  for ( Size ii = 0; ii < n_overlap[ 1 ]; ++ii ) {
554  my_pos[ 1 ] = my_grid_start[ 1 ] + ii;
555  other_pos[ 1 ] = other_grid_start[ 1 ] + ii;
556  for ( Size jj = 0; jj < n_overlap[ 2 ]; ++jj ) {
557  my_pos[ 2 ] = my_grid_start[ 2 ] + jj;
558  other_pos[ 2 ] = other_grid_start[ 2 ] + jj;
559  for ( Size kk = 0; kk < n_overlap[ 3 ]; ++kk ) {
560  my_pos[ 3 ] = my_grid_start[ 3 ] + kk;
561  other_pos[ 3 ] = other_grid_start[ 3 ] + kk;
562 
563  index_mask_pair my_indmask = index_and_mask_for_bin( my_pos );
564  index_mask_pair other_indmask = other.index_and_mask_for_bin( other_pos );
565  if ( grid_[ my_indmask.first ] & my_indmask.second ) continue;
566  if ( other.grid_[ other_indmask.first ] & other_indmask.second ) {
567  grid_[ my_indmask.first ] |= my_indmask.second;
568  }
569  }
570  }
571  }
572 
573 }
574 
575 void Bool3DGrid::and_with( Bool3DGrid const & other )
576 {
577  assert( bin_width_ == other.bin_width_ );
578 
579  /// 1. Compute the bin overlap
580  Vector overlap_low(
581  std::max( bb_.lower().x(), other.bb_.lower().x() ),
582  std::max( bb_.lower().y(), other.bb_.lower().y() ),
583  std::max( bb_.lower().z(), other.bb_.lower().z() ) );
584 
585  Vector overlap_high(
586  std::min( bb_.upper().x(), other.bb_.upper().x() ),
587  std::min( bb_.upper().y(), other.bb_.upper().y() ),
588  std::min( bb_.upper().z(), other.bb_.upper().z() ) );
589 
590  /// Check for a situation in which the grids have no overlap.
591  if ( overlap_low.x() >= overlap_high.x() ||
592  overlap_low.y() >= overlap_high.y() ||
593  overlap_low.z() >= overlap_high.z() ) return;
594 
595  /// Assert that the two grids are compatible: that the region of overlap perfectly
596  /// contains all the voxels inside of it (no voxels spill out).
597  assert( std::abs( (overlap_low.x() - bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - bb_.lower().x()) / bin_width_ )) < 1e-6 );
598  assert( std::abs( (overlap_low.y() - bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - bb_.lower().y()) / bin_width_ )) < 1e-6 );
599  assert( std::abs( (overlap_low.z() - bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - bb_.lower().z()) / bin_width_ )) < 1e-6 );
600 
601  assert( std::abs( (overlap_low.x() - other.bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - other.bb_.lower().x()) / bin_width_ )) < 1e-6 );
602  assert( std::abs( (overlap_low.y() - other.bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - other.bb_.lower().y()) / bin_width_ )) < 1e-6 );
603  assert( std::abs( (overlap_low.z() - other.bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - other.bb_.lower().z()) / bin_width_ )) < 1e-6 );
604 
605  /// Iterate over the grid indices of this and other in the overlapping region.
606  Bin3D n_overlap;
607  Real const perturb = bin_width_ / 2;
608  n_overlap[ 1 ] = static_cast< Size > (( overlap_high.x() - overlap_low.x() + perturb ) / bin_width_ );
609  n_overlap[ 2 ] = static_cast< Size > (( overlap_high.y() - overlap_low.y() + perturb ) / bin_width_ );
610  n_overlap[ 3 ] = static_cast< Size > (( overlap_high.z() - overlap_low.z() + perturb ) / bin_width_ );
611 
612  Bin3D my_grid_start;
613  my_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - bb_.lower().x() + perturb ) / bin_width_ );
614  my_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - bb_.lower().y() + perturb ) / bin_width_ );
615  my_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - bb_.lower().z() + perturb ) / bin_width_ );
616 
617  Bin3D other_grid_start;
618  other_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - other.bb_.lower().x() + perturb ) / bin_width_ );
619  other_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - other.bb_.lower().y() + perturb ) / bin_width_ );
620  other_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - other.bb_.lower().z() + perturb ) / bin_width_ );
621 
622  Bin3D my_pos;
623  Bin3D other_pos;
624 
625  for ( Size ii = 0; ii < n_overlap[ 1 ]; ++ii ) {
626  my_pos[ 1 ] = my_grid_start[ 1 ] + ii;
627  other_pos[ 1 ] = other_grid_start[ 1 ] + ii;
628  for ( Size jj = 0; jj < n_overlap[ 2 ]; ++jj ) {
629  my_pos[ 2 ] = my_grid_start[ 2 ] + jj;
630  other_pos[ 2 ] = other_grid_start[ 2 ] + jj;
631  for ( Size kk = 0; kk < n_overlap[ 3 ]; ++kk ) {
632  my_pos[ 3 ] = my_grid_start[ 3 ] + kk;
633  other_pos[ 3 ] = other_grid_start[ 3 ] + kk;
634 
635  index_mask_pair my_indmask = index_and_mask_for_bin( my_pos );
636  index_mask_pair other_indmask = other.index_and_mask_for_bin( other_pos );
637  if ( ! grid_[ my_indmask.first ] & my_indmask.second ) continue;
638  if ( other.grid_[ other_indmask.first ] & other_indmask.second ) continue;
639  grid_[ my_indmask.first ] &= ~my_indmask.second; // set the bit to 0.
640  }
641  }
642  }
643 
644 
645 }
646 
647 /// @details Set all the values in this grid to "false" that are true in the other grid.
648 void Bool3DGrid::subtract( Bool3DGrid const & other )
649 {
650  assert( bin_width_ == other.bin_width_ );
651 
652  /// 1. Compute the bin overlap
653  Vector overlap_low(
654  std::max( bb_.lower().x(), other.bb_.lower().x() ),
655  std::max( bb_.lower().y(), other.bb_.lower().y() ),
656  std::max( bb_.lower().z(), other.bb_.lower().z() ) );
657 
658  Vector overlap_high(
659  std::min( bb_.upper().x(), other.bb_.upper().x() ),
660  std::min( bb_.upper().y(), other.bb_.upper().y() ),
661  std::min( bb_.upper().z(), other.bb_.upper().z() ) );
662 
663  /// Check for a situation in which the grids have no overlap.
664  if ( overlap_low.x() >= overlap_high.x() ||
665  overlap_low.y() >= overlap_high.y() ||
666  overlap_low.z() >= overlap_high.z() ) return;
667 
668  /// Assert that the two grids are compatible: that the region of overlap perfectly
669  /// contains all the voxels inside of it (no voxels spill out).
670  assert( std::abs( (overlap_low.x() - bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - bb_.lower().x()) / bin_width_ )) < 1e-6 );
671  assert( std::abs( (overlap_low.y() - bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - bb_.lower().y()) / bin_width_ )) < 1e-6 );
672  assert( std::abs( (overlap_low.z() - bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - bb_.lower().z()) / bin_width_ )) < 1e-6 );
673 
674  assert( std::abs( (overlap_low.x() - other.bb_.lower().x()) - bin_width_ * static_cast< int > ((overlap_low.x() - other.bb_.lower().x()) / bin_width_ )) < 1e-6 );
675  assert( std::abs( (overlap_low.y() - other.bb_.lower().y()) - bin_width_ * static_cast< int > ((overlap_low.y() - other.bb_.lower().y()) / bin_width_ )) < 1e-6 );
676  assert( std::abs( (overlap_low.z() - other.bb_.lower().z()) - bin_width_ * static_cast< int > ((overlap_low.z() - other.bb_.lower().z()) / bin_width_ )) < 1e-6 );
677 
678  /// Iterate over the grid indices of this and other in the overlapping region.
679  Bin3D n_overlap;
680  Real const perturb = bin_width_ / 2;
681  n_overlap[ 1 ] = static_cast< Size > (( overlap_high.x() - overlap_low.x() + perturb ) / bin_width_ );
682  n_overlap[ 2 ] = static_cast< Size > (( overlap_high.y() - overlap_low.y() + perturb ) / bin_width_ );
683  n_overlap[ 3 ] = static_cast< Size > (( overlap_high.z() - overlap_low.z() + perturb ) / bin_width_ );
684 
685  Bin3D my_grid_start;
686  my_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - bb_.lower().x() + perturb ) / bin_width_ );
687  my_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - bb_.lower().y() + perturb ) / bin_width_ );
688  my_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - bb_.lower().z() + perturb ) / bin_width_ );
689 
690  Bin3D other_grid_start;
691  other_grid_start[ 1 ] = static_cast< Size > (( overlap_low.x() - other.bb_.lower().x() + perturb ) / bin_width_ );
692  other_grid_start[ 2 ] = static_cast< Size > (( overlap_low.y() - other.bb_.lower().y() + perturb ) / bin_width_ );
693  other_grid_start[ 3 ] = static_cast< Size > (( overlap_low.z() - other.bb_.lower().z() + perturb ) / bin_width_ );
694 
695  Bin3D my_pos;
696  Bin3D other_pos;
697 
698  for ( Size ii = 0; ii < n_overlap[ 1 ]; ++ii ) {
699  my_pos[ 1 ] = my_grid_start[ 1 ] + ii;
700  other_pos[ 1 ] = other_grid_start[ 1 ] + ii;
701  for ( Size jj = 0; jj < n_overlap[ 2 ]; ++jj ) {
702  my_pos[ 2 ] = my_grid_start[ 2 ] + jj;
703  other_pos[ 2 ] = other_grid_start[ 2 ] + jj;
704  for ( Size kk = 0; kk < n_overlap[ 3 ]; ++kk ) {
705  my_pos[ 3 ] = my_grid_start[ 3 ] + kk;
706  other_pos[ 3 ] = other_grid_start[ 3 ] + kk;
707 
708  index_mask_pair my_indmask = index_and_mask_for_bin( my_pos );
709  index_mask_pair other_indmask = other.index_and_mask_for_bin( other_pos );
710  if ( ! grid_[ my_indmask.first ] & my_indmask.second ) continue;
711 
712  if ( ! other.grid_[ other_indmask.first ] & other_indmask.second ) continue;
713 
714  grid_[ my_indmask.first ] &= ~my_indmask.second; // set the bit to 0.
715  }
716  }
717  }
718 
719 
720 }
721 
722 
724 {
725  for ( Size ii = 0; ii < grid_.size(); ++ii ) {
726  grid_[ ii ] = 0;
727  }
728 }
729 
730 
733 {
734  Vector local = point - bb_.lower();
735  Bin3D halfbin;
736  halfbin[ 1 ] = static_cast< Size > ( local.x() / bin_width_2x_ );
737  halfbin[ 2 ] = static_cast< Size > ( local.y() / bin_width_2x_ );
738  halfbin[ 3 ] = static_cast< Size > ( local.z() / bin_width_2x_ );
739  Size xmod2 = local.x() - halfbin[ 1 ] * bin_width_2x_ >= bin_width_ ? 1 : 0;
740  Size ymod2 = local.y() - halfbin[ 2 ] * bin_width_2x_ >= bin_width_ ? 1 : 0;
741  Size zmod2 = local.z() - halfbin[ 3 ] * bin_width_2x_ >= bin_width_ ? 1 : 0;
742 
743  //std::cout << "index for point " << point.x() << " " << point.y() << " " << point.z() << " ";
744  //std::cout << "local point: " << local.x() << " " << local.y() << " " << local.z() << " ";
745  //std::cout << "lower bound: " << bb_.lower().x() << " " << bb_.lower().y() << " " << bb_.lower().z() << " halfbin: ";
746  //std::cout << halfbin[ 1 ] << " " << halfbin[ 2 ] << " " << halfbin[ 3 ] << " halfdimprods:";
747  //std::cout << halfdimprods_[ 1 ] << " " << halfdimprods_[ 2 ] << " " << halfdimprods_[ 3 ] << " " << std::endl;
748 
749  Size index = byte_index_from_doublebin( halfbin );
750  unsigned char mask = mask_from_offsets( xmod2, ymod2, zmod2 );
751 
752  return std::make_pair( index, mask );
753 }
754 
757 {
758  Bin3D halfbin;
759  halfbin[ 1 ] = bin[ 1 ] / 2;
760  halfbin[ 2 ] = bin[ 2 ] / 2;
761  halfbin[ 3 ] = bin[ 3 ] / 2;
762  Size xmod2 = bin[ 1 ] % 2;
763  Size ymod2 = bin[ 2 ] % 2;
764  Size zmod2 = bin[ 3 ] % 2;
765 
766  //std::cout << "index for point " << point.x() << " " << point.y() << " " << point.z() << " ";
767  //std::cout << "local point: " << local.x() << " " << local.y() << " " << local.z() << " ";
768  //std::cout << "lower bound: " << bb_.lower().x() << " " << bb_.lower().y() << " " << bb_.lower().z() << " halfbin: ";
769  //std::cout << halfbin[ 1 ] << " " << halfbin[ 2 ] << " " << halfbin[ 3 ] << " halfdimprods:";
770  //std::cout << halfdimprods_[ 1 ] << " " << halfdimprods_[ 2 ] << " " << halfdimprods_[ 3 ] << " " << std::endl;
771 
772  Size index = byte_index_from_doublebin( halfbin );
773  unsigned char mask = mask_from_offsets( xmod2, ymod2, zmod2 );
774 
775  return std::make_pair( index, mask );
776 }
777 
779 Bool3DGrid::bin_for_point( Vector const & point ) const
780 {
781  assert( bb_.contains( point ) );
782  Vector local = point - bb_.lower();
783  Bin3D bin;
784  bin[ 1 ] = static_cast< Size > ( local.x() / bin_width_ );
785  bin[ 2 ] = static_cast< Size > ( local.y() / bin_width_ );
786  bin[ 3 ] = static_cast< Size > ( local.z() / bin_width_ );
787  if ( bin[ 1 ] >= dimsizes_[ 1 ] ) bin[ 1 ] = dimsizes_[ 1 ] - 1;
788  if ( bin[ 2 ] >= dimsizes_[ 2 ] ) bin[ 2 ] = dimsizes_[ 2 ] - 1;
789  if ( bin[ 3 ] >= dimsizes_[ 3 ] ) bin[ 3 ] = dimsizes_[ 3 ] - 1;
790  return bin;
791 }
792 
793 void
795  Vector local_upper_corner = bb_.upper() - bb_.lower();
796  Bin3D nbins;
797  Real const perturb( bin_width_ * 0.5 );
798  nbins[ 1 ] = static_cast< Size > ( (local_upper_corner.x() + perturb ) / bin_width_ );
799  nbins[ 2 ] = static_cast< Size > ( (local_upper_corner.y() + perturb ) / bin_width_ );
800  nbins[ 3 ] = static_cast< Size > ( (local_upper_corner.z() + perturb ) / bin_width_ );
801 
802  if ( nbins[ 1 ] * bin_width_ < local_upper_corner.x() ) ++nbins[ 1 ];
803  if ( nbins[ 2 ] * bin_width_ < local_upper_corner.y() ) ++nbins[ 2 ];
804  if ( nbins[ 3 ] * bin_width_ < local_upper_corner.z() ) ++nbins[ 3 ];
805 
806  for ( Size ii = 1; ii <= 3; ++ii ) {
807  // make nbins a multiple of the number of bins per super voxel
808  // The number of double-bins per supervoxel may be any value, however,
809  // the number of bins per supervoxel must be even.
810  nbins[ ii ] += nbins[ ii ] % ( 2 * n_doublebins_per_supervoxel ) == 0 ?
811  0 : 2 * n_doublebins_per_supervoxel - nbins[ ii ] % ( 2 * n_doublebins_per_supervoxel );
812  dimsizes_[ ii ] = nbins[ ii ];
813  halfdimsizes_[ ii ] = nbins[ ii ] / 2;
815  }
816 
817 
818  Vector new_upper( bb_.lower() );
819  new_upper.x() += bin_width_ * ( dimsizes_[ 1 ] );
820  new_upper.y() += bin_width_ * ( dimsizes_[ 2 ] );
821  new_upper.z() += bin_width_ * ( dimsizes_[ 3 ] );
822 
823  bb_extended_ = BoundingBox( bb_.lower(), new_upper );
824 
825  dimprods_[ 3 ] = 1;
826  halfdimprods_[ 3 ] = 1;
827  supervoxel_dimprods_[ 3 ] = 1;
828 
829  dimprods_[ 2 ] = dimsizes_[ 3 ];
830  halfdimprods_[ 2 ] = halfdimsizes_[ 3 ];
832 
833  dimprods_[ 1 ] = dimprods_[ 2 ] * dimsizes_[ 2 ];
834  halfdimprods_[ 1 ] = halfdimprods_[ 2 ] * halfdimsizes_[ 2 ];
836 
837  Size nchar = halfdimprods_[ 1 ] * halfdimsizes_[ 1 ];
838  grid_.resize( nchar );
839  std::fill( grid_.begin(), grid_.end(), (unsigned char) 0 );
840 
842  half_bin_width_root_three_ = bin_width_ * 0.5 * std::sqrt( 3.0 ); // the distance from the each corner of a voxel to the center.
843 
844  //std::cout << "Bool3DGrid Constructor:\n nbins: " << nbins[ 1 ] << " " << nbins[ 2 ] << " " << nbins[ 3 ] << "\n";
845  //std::cout << " dimprods" << dimprods_[ 1 ] << " " << dimprods_[ 2 ] << " " << dimprods_[ 3 ] << "\n";
846  //std::cout << " halfdimsizes_" << halfdimsizes_[ 1 ] << " " << halfdimsizes_[ 2 ] << " " << halfdimsizes_[ 3 ] << "\n";
847  //std::cout << " halfdimprods_" << halfdimprods_[ 1 ] << " " << halfdimprods_[ 2 ] << " " << halfdimprods_[ 3 ] << "\n";
848  //std::cout << " supervoxel_dimsizes_" << supervoxel_dimsizes_[ 1 ] << " " << supervoxel_dimsizes_[ 2 ] << " " << supervoxel_dimsizes_[ 3 ] << "\n";
849  //std::cout << " supervoxel_dimprods_" << supervoxel_dimprods_[ 1 ] << " " << supervoxel_dimprods_[ 2 ] << " " << supervoxel_dimprods_[ 3 ] << "\n";
850  //std::cout << "bin width: " << bin_width_ << " bin width 2x " << bin_width_2x_ << "\n";
851  //std::cout << std::endl;
852 }
853 
854 
855 
856 unsigned char
857 Bool3DGrid::mask_from_offsets( Size xmod2, Size ymod2, Size zmod2 ) const
858 {
859  assert( xmod2 == 0 || xmod2 == 1 );
860  assert( ymod2 == 0 || ymod2 == 1 );
861  assert( zmod2 == 0 || zmod2 == 1 );
862 
863  Size offset = 4 * xmod2 + 2 * ymod2 + zmod2;
864  switch ( offset ) {
865  case 0 : return 0x01;
866  case 1 : return 0x02;
867  case 2 : return 0x04;
868  case 3 : return 0x08;
869  case 4 : return 0x10;
870  case 5 : return 0x20;
871  case 6 : return 0x40;
872  case 7 : return 0x80;
873  }
874  utility_exit_with_message( "ERROR: Bad input to Bool3DGrid mask from offsets" );
875  return 0x0;
876 }
877 
878 unsigned char
879 Bool3DGrid::negmask_from_offsets( Size xmod2, Size ymod2, Size zmod2 ) const
880 {
881  assert( xmod2 == 0 || xmod2 == 1 );
882  assert( ymod2 == 0 || ymod2 == 1 );
883  assert( zmod2 == 0 || zmod2 == 1 );
884 
885  Size offset = 4 * xmod2 + 2 * ymod2 + zmod2;
886  switch ( offset ) {
887  case 0 : return 0xFE;
888  case 1 : return 0xFD;
889  case 2 : return 0xFB;
890  case 3 : return 0xF7;
891  case 4 : return 0xEF;
892  case 5 : return 0xDF;
893  case 6 : return 0xBF;
894  case 7 : return 0x7F;
895  }
896  utility_exit_with_message( "ERROR: Bad input to Bool3DGrid negmask from offsets" );
897  return 0x0;
898 
899 }
900 
902 Bool3DGrid::byte_index_from_doublebin( Bin3D const & doublebin ) const {
903 
904  assert( doublebin[ 1 ] < halfdimsizes_[ 1 ] );
905  assert( doublebin[ 2 ] < halfdimsizes_[ 2 ] );
906  assert( doublebin[ 3 ] < halfdimsizes_[ 3 ] );
907 
908  Size index =
909  supervoxel_dimprods_[ 1 ] * ( doublebin[ 1 ] / n_doublebins_per_supervoxel ) +
910  supervoxel_dimprods_[ 2 ] * ( doublebin[ 2 ] / n_doublebins_per_supervoxel ) +
911  ( doublebin[ 3 ] / n_doublebins_per_supervoxel ); // supervoxel index;
912  /// must be converted into the starting position for that supervoxel:
913 
915 
916  index += n_doublebins_per_supervoxel * n_doublebins_per_supervoxel * (doublebin[ 1 ] % n_doublebins_per_supervoxel );
917  index += n_doublebins_per_supervoxel * (doublebin[ 2 ] % n_doublebins_per_supervoxel );
918  index += doublebin[ 3 ] % n_doublebins_per_supervoxel;
919 
920  return index;
921 }
922 
923 
924 
925 /////////////////////// BUMP GRID ////////////////////////////////////
927  grids_( n_probe_radii, 0 ),
928  pair_permit_overlap_( n_probe_radii ),
929  general_permit_overlap_( 0.0 )
930 {
931  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
932  grids_[ ii ] = new Bool3DGrid;
933  pair_permit_overlap_[ ii ].resize( n_probe_radii );
934  std::fill ( pair_permit_overlap_[ ii ].begin(), pair_permit_overlap_[ ii ].end(), 0.0 );
935  }
936 
937  Real const permit_overlap[ n_probe_radii + 1 ][ n_probe_radii + 1 ] = {
938  /// ZERO, H_ARO, H_ALA, OXY, NIT, C_CAR, C_ALA, SULPH
939  { 0, 0, 0, 0, 0, 0, 0, 0 }, // ZERO
940  { 0, 0, 0, 0.5, 0.5, 0, 0, 0 }, // H_ARO
941  { 0, 0, 0, 0, 0, 0, 0, 0 }, // H_ALA
942  { 0, 0.5, 0, 0.3, 0.3, 0, 0, 0 }, // OXY
943  { 0, 0.5, 0, 0.3, 0.3, 0, 0, 0 }, // NIT
944  { 0, 0, 0, 0, 0, 0, 0, 0 }, // C_CAR
945  { 0, 0, 0, 0, 0, 0, 0, 0 }, // C_ALA
946  { 0, 0, 0, 0, 0, 0, 0, 0 }};// SULPH
947 
948  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
949  for ( Size jj = 1; jj <= n_probe_radii; ++jj ) {
950  pair_permit_overlap_[ ii ][ jj ] = permit_overlap[ ii ][ jj ];
951  }
952  }
953 
954 }
955 
956 BumpGrid::BumpGrid( BumpGrid const & rhs ) :
957  parent(),
958  grids_( n_probe_radii, 0 ),
959  pair_permit_overlap_( rhs.pair_permit_overlap_ ),
960  general_permit_overlap_( rhs.general_permit_overlap_ )
961 {
962  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
963  grids_[ ii ] = new Bool3DGrid( *rhs.grids_[ ii ] );
964  }
965 }
966 
968 
970 {
971  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
972  grids_[ ii ] = new Bool3DGrid( *rhs.grids_[ ii ] );
973  }
976 
977  return *this;
978 }
979 
980 // @details This function assumes that the bounding box is large enough
981 // to contain all of the (real space) spheres. Make this bounding box large
982 // enough to hold all of the configuration space spheres -- extend each
983 // dimension by the largest probe radius. Then extend each dimension to an
984 // integer.
986 {
987  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
988  Vector lower = bb.lower() - probe_radius( (ProbeRadius) ii );
989  lower.x() = static_cast< Real > ( static_cast< int > ( lower.x() ));
990  lower.y() = static_cast< Real > ( static_cast< int > ( lower.y() ));
991  lower.z() = static_cast< Real > ( static_cast< int > ( lower.z() ));
992  Vector upper = bb.upper() + probe_radius( (ProbeRadius) ii );
993  BoundingBox iibb( lower, upper );
994  grids_[ ii ] = new Bool3DGrid;
995  grids_[ ii ]->set_bin_width( 0.25 ); /// HARD CODED HACK!
996  grids_[ ii ]->set_bounding_box( iibb );
997  }
998 
999 }
1000 
1001 
1002 /// @details The input bounding box is assumed to hold all of the (real space)
1003 /// spheres that should be represented. Create a larger bounding box big enough
1004 /// to hold all of the configuration space spheres.
1005 BumpGrid
1007 {
1008  BumpGrid stub;
1009 
1010  /// Initialize the new BumpGrid with the sphere overlap parameters held in this bump grid
1013 
1014  stub.set_bounding_box( bb );
1015  return stub;
1016 }
1017 
1018 BumpGridOP
1020  BumpGridOP bgop = new BumpGrid;
1021 
1022  /// Initialize the new BumpGrid with the sphere overlap parameters held in this bump grid
1023  bgop->pair_permit_overlap_ = pair_permit_overlap_;
1024  bgop->general_permit_overlap_ = general_permit_overlap_;
1025 
1026  bgop->set_bounding_box( bb );
1027  return bgop;
1028 }
1029 
1030 void BumpGrid::or_with( BumpGrid const & other )
1031 {
1032  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
1033  if ( grids_[ ii ]->actual_bb().intersects( other.grids_[ ii ]->actual_bb() ) ) {
1034  grids_[ ii ]->or_with( *other.grids_[ ii ] );
1035  }
1036  }
1037 }
1038 void BumpGrid::and_with( BumpGrid const & other )
1039 {
1040  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
1041  if ( grids_[ ii ]->actual_bb().intersects( other.grids_[ ii ]->actual_bb() ) ) {
1042  grids_[ ii ]->and_with( *other.grids_[ ii ] );
1043  }
1044  }
1045 }
1046 
1047 /// @details Input sphere is a real-space sphere -- it's radius will be increased by the
1048 /// varying probe radii to create the varying configuration-space spheres.
1049 void BumpGrid::or_by_sphere( Sphere const & input )
1050 {
1051  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
1052  grids_[ ii ]->or_by_sphere_conservative( input.first, input.second + probe_radius( (ProbeRadius) ii ) );
1053  }
1054 
1055 }
1056 
1058  Vector const & center, ProbeRadius radius_type
1059 )
1060 {
1061  if ( radius_type == ZERO ) return;
1062 
1063  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
1064  grids_[ ii ]->or_by_sphere_conservative( center,
1065  required_separation_distance( ProbeRadius( ii ), radius_type ) );
1066  }
1067 }
1068 
1069 bool BumpGrid::overlaps( BumpGrid const & other ) const {
1070 
1071  for ( Size ii = 1; ii <= n_probe_radii; ++ii ) {
1072  if ( grids_[ ii ]->actual_bb().intersects( other.grids_[ ii ]->actual_bb() ) ) {
1073  return true;
1074  }
1075  }
1076  return false;
1077 }
1078 
1079 /// @brief Collision detection by a point p with a given (fixed) radius type.
1080 /// Collision detection is performed in "configuration space", where the obstacles
1081 /// have been convolved with a spherical probe of a given radius. This collision
1082 /// detection is conservative: it will not report a collision to exist that does not,
1083 /// but may miss a collision that does exist.
1084 bool BumpGrid::occupied( ProbeRadius radius_type, Vector const & p ) const
1085 {
1086  if ( radius_type == ZERO ) return false;
1087  if ( grids_[ radius_type ]->actual_bb().contains( p ) ) {
1088  return grids_[ radius_type ]->occupied( p );
1089  }
1090 
1091  return false;
1092 }
1093 
1095 {
1096  general_permit_overlap_ = tolerated_overlap;
1097 }
1098 
1099 
1101 {
1102  pair_permit_overlap_[ rad1 ][ rad2 ] = tolerated_overlap;
1103  pair_permit_overlap_[ rad2 ][ rad1 ] = tolerated_overlap;
1104 }
1105 
1108 {
1109  return pair_permit_overlap_[ rad1 ][ rad2 ];
1110 }
1111 
1114 {
1115  using namespace core;
1116  using namespace core::chemical;
1117 
1119  utility::vector1< ProbeRadius > attype_2_radtype( atset->n_atomtypes(), ZERO );
1120  for ( Size ii = 1; ii <= atset->n_atomtypes(); ++ii ) {
1121  ProbeRadius ii_probe_radius( ZERO );
1122  AtomType const & iiat( (*atset)[ ii ] );
1123  if ( iiat.element() == "H" ) {
1124  if ( iiat.name() == "Hapo" ) ii_probe_radius = H_ALA;
1125  else ii_probe_radius = H_ARO; // covers Haro, Hpol, HNbb, and HOH
1126  } else if ( iiat.element() == "N" ) {
1127  ii_probe_radius = NIT;
1128  } else if ( iiat.element() == "O" ) {
1129  ii_probe_radius = OXY;
1130  } else if ( iiat.element() == "C" ) {
1131  if ( iiat.name() == "CNH2" || iiat.name() == "COO" || iiat.name() == "CObb" ) ii_probe_radius = C_CAR;
1132  else ii_probe_radius = C_ALA;
1133  } else if ( iiat.element() == "P" || iiat.element() == "S" ) {
1134  ii_probe_radius = SULPH;
1135  } else if ( iiat.lj_radius() == 0.0 ) {
1136  ii_probe_radius = ZERO;
1137  } else {
1138  /// find the next smallest probe radius -- this will produce a conservative set of collisions,
1139  /// as some radii pairs tolerate some collision to describe hydrogen bonds.
1140  Real radius_shrunk = 0.89 * iiat.lj_radius();
1141  for ( Size jj = 1; jj <= n_probe_radii; ++jj ) {
1142  Real rad = BumpGrid::probe_radius( (ProbeRadius) jj );
1143  if ( rad <= radius_shrunk ) {
1144  ii_probe_radius = (ProbeRadius) jj;
1145  } else {
1146  break;
1147  }
1148  }
1149  }
1150  attype_2_radtype[ ii ] = ii_probe_radius;
1151  TR << "Atom type " << iiat.name() << " with ProbeRadius " << ii_probe_radius
1152  << " = " << BumpGrid::probe_radius( (ProbeRadius) ii_probe_radius ) << std::endl;
1153  }
1154  return attype_2_radtype;
1155 }
1156 
1159 {
1160  static const utility::vector1< ProbeRadius > attype_2_probe_radius( initialize_atomtype_2_probe_radius_map() );
1161  return attype_2_probe_radius[ atomtype ];
1162 }
1163 
1164 //// Useful non-member functions for BumpGrid.
1165 BumpGridOP
1167 {
1168  using namespace core;
1169 
1170  Vector first_xyz( 0 );
1171  Real at1rad( 0.0 );
1172 
1173  if ( pose.total_residue() < 1 ) {
1174  return new BumpGrid;
1175  } else {
1176  bool found_an_atom( false );
1177  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
1178  if ( pose.residue( ii ).natoms() > 0 ) {
1179  first_xyz = pose.residue( ii ).xyz( 1 );
1180  at1rad = probe_radius_for_atom_type( pose.residue( ii ).atom( 1 ).type() );
1181  found_an_atom = true;
1182  break;
1183  }
1184  }
1185  if ( ! found_an_atom ) {
1186  /// weird non-empty pose where each residue has 0 atoms?
1187  return new BumpGrid;
1188  }
1189  }
1190 
1191  Vector bbl( first_xyz - at1rad ), bbu( first_xyz + at1rad );
1192  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
1193  for ( Size jj = 1; jj <= pose.residue( ii ).natoms(); ++jj ) {
1195  bbl.min( pose.residue( ii ).xyz( jj ) - jjrad );
1196  bbu.max( pose.residue( ii ).xyz( jj ) + jjrad );
1197  }
1198  }
1199 
1200  BumpGridOP bgop = new BumpGrid;
1201  numeric::geometry::BoundingBox< Vector > bb( bbl, bbu );
1202  bgop->set_bounding_box( bb );
1203 
1204  return bgop;
1205 }
1206 
1208  core::conformation::Residue const & residue,
1209  BumpGrid const & original_grid
1210 )
1211 {
1212  using namespace core;
1213 
1214  Vector first_xyz( 0 );
1215 
1216  if ( residue.natoms() < 1 ) {
1217  return new BumpGrid;
1218  } else {
1219  first_xyz = residue.xyz( 1 );
1220  }
1221 
1222  Real at1rad = probe_radius_for_atom_type( residue.atom( 1 ).type() );
1223 
1224  core::Vector bbl( first_xyz - at1rad ), bbu( first_xyz + at1rad );
1225  //core::Vector bbl_strict( first_xyz ), bbu_strict( first_xyz );
1226 
1227  for ( Size ii = 2; ii <= residue.last_backbone_atom(); ++ii ) {
1228  Real iirad = BumpGrid::probe_radius( probe_radius_for_atom_type( residue.atom( ii ).type() ));
1229  bbl.min( residue.xyz( ii ) - iirad );
1230  bbu.max( residue.xyz( ii ) + iirad );
1231  }
1232 
1233  numeric::geometry::BoundingBox< Vector > bb( bbl, bbu );
1234  return original_grid.create_new_bump_grid_for_bb( bb );
1235 }
1236 
1238  core::conformation::Residue const & residue,
1239  BumpGrid const & original_grid
1240 )
1241 {
1242  using namespace core;
1243 
1244  Vector first_xyz( 0 );
1245 
1246  if ( residue.natoms() < 1 ) {
1247  return new BumpGrid;
1248  } else {
1249  first_xyz = residue.xyz( 1 );
1250  }
1251 
1252  Real at1rad = probe_radius_for_atom_type( residue.atom( 1 ).type() );
1253 
1254  core::Vector bbl( first_xyz - at1rad ), bbu( first_xyz + at1rad );
1255  //core::Vector bbl_strict( first_xyz ), bbu_strict( first_xyz );
1256 
1257  for ( Size ii = 2; ii <= residue.natoms(); ++ii ) {
1258  Real iirad = BumpGrid::probe_radius( probe_radius_for_atom_type( residue.atom( ii ).type() ));
1259  bbl.min( residue.xyz( ii ) - iirad );
1260  bbu.max( residue.xyz( ii ) + iirad );
1261  }
1262 
1263  numeric::geometry::BoundingBox< Vector > bb( bbl, bbu );
1264 
1265  return original_grid.create_new_bump_grid_for_bb( bb );
1266 
1267 }
1268 
1269 void
1271  core::conformation::Residue const & residue,
1272  BumpGrid & grid
1273 )
1274 {
1275  using namespace core;
1276  for ( Size ii = 1; ii <= residue.natoms(); ++ii ) {
1277  grid.or_by_sphere( residue.xyz( ii ), probe_radius_for_atom_type( residue.atom( ii ).type() ));
1278  }
1279 }
1280 
1281 void
1283  core::conformation::Residue const & residue,
1284  BumpGrid & grid
1285 )
1286 {
1287  using namespace core;
1288  for ( Size ii = 1; ii <= residue.nheavyatoms(); ++ii ) {
1289  grid.or_by_sphere( residue.xyz( ii ), probe_radius_for_atom_type( residue.atom( ii ).type() ));
1290  }
1291 }
1292 
1293 
1294 void
1296  core::conformation::Residue const & residue,
1297  BumpGrid & grid
1298 )
1299 {
1300  using namespace core;
1301  for ( Size ii = 1; ii <= residue.last_backbone_atom(); ++ii ) {
1302  grid.or_by_sphere( residue.xyz( ii ), probe_radius_for_atom_type( residue.atom( ii ).type() ));
1303  }
1304 }
1305 
1306 
1308  unselectable_( true ),
1309  line_color_( "red" ),
1310  master_( "grid" ),
1311  shrink_factor_( 0.75 ),
1312  skip_completely_buried_positions_( true ),
1313  write_empty_voxels_( false ),
1314  empty_voxel_color_( "gray" ),
1315  write_facets_( false ),
1316  facet_master_( "grid facets" ),
1317  facet_color_( "pinktint" ),
1318  transparent_facets_( false ),
1319  facet_alpha_( 1.0 )
1320 {}
1321 
1323 
1324 void Bool3DGridKinemageWriter::set_unselectable( bool unselectable ) { unselectable_ = unselectable; }
1325 void Bool3DGridKinemageWriter::set_line_color( std::string const & line_color ) { line_color_ = line_color; }
1326 void Bool3DGridKinemageWriter::set_master( std::string const & master ) { master_ = master; }
1327 void Bool3DGridKinemageWriter::set_shrink_factor( Real shrink_factor ) { shrink_factor_ = shrink_factor; }
1328 void Bool3DGridKinemageWriter::set_skip_completely_buried_positions( bool skip_completely_buried_positions ) { skip_completely_buried_positions_ = skip_completely_buried_positions; }
1329 
1330 void Bool3DGridKinemageWriter::set_write_empty_voxels( bool write_empty_voxels ) { write_empty_voxels_ = write_empty_voxels; }
1331 void Bool3DGridKinemageWriter::set_empty_voxel_color( std::string const & empty_voxel_color ) { empty_voxel_color_ = empty_voxel_color; }
1332 
1333 void Bool3DGridKinemageWriter::set_write_facets( bool write_facets ) { write_facets_ = write_facets; }
1334 void Bool3DGridKinemageWriter::set_facet_master( std::string const & facet_master ) { facet_master_ = facet_master; }
1335 void Bool3DGridKinemageWriter::set_facet_color( std::string const & facet_color ) { facet_color_ = facet_color; }
1336 void Bool3DGridKinemageWriter::set_transparent_facets( bool transparent_facets ) { transparent_facets_ = transparent_facets; }
1337 void Bool3DGridKinemageWriter::set_facet_alpha( Real facet_alpha ) { facet_alpha_ = facet_alpha; }
1338 
1340  std::ostream & ostr,
1341  std::string const & group_name,
1342  Bool3DGrid const & grid
1343 ) const
1344 {
1345  Bool3DGrid::CornerPoints corner_offsets;
1346 
1347  /// Shrink in from the corners by an offset determined by the "shrink factor" and the bin width.
1348  corner_offsets[ 1 ] = shrink_factor_ * grid.bin_width() * Vector( 1, 1, 1 );
1349  corner_offsets[ 2 ] = shrink_factor_ * grid.bin_width() * Vector( 1, 1, -1 );
1350  corner_offsets[ 3 ] = shrink_factor_ * grid.bin_width() * Vector( 1, -1, 1 );
1351  corner_offsets[ 4 ] = shrink_factor_ * grid.bin_width() * Vector( 1, -1, -1 );
1352  corner_offsets[ 5 ] = shrink_factor_ * grid.bin_width() * Vector( -1, 1, 1 );
1353  corner_offsets[ 6 ] = shrink_factor_ * grid.bin_width() * Vector( -1, 1, -1 );
1354  corner_offsets[ 7 ] = shrink_factor_ * grid.bin_width() * Vector( -1, -1, 1 );
1355  corner_offsets[ 8 ] = shrink_factor_ * grid.bin_width() * Vector( -1, -1, -1 );
1356 
1357  Size const A( 1 ), B( 5 ), C( 7 ), D( 3 ), E( 2 ), F( 6 ), G( 8 ), H( 4 );
1358 
1359  ostr << "@group {" << group_name << "} dominant\n";
1360  ostr << "@vectorlist {} color= " << line_color_ << " width= 1\n";
1361 
1362  Bin3D ndims = grid.dimsizes();
1363  Bin3D bin;
1364 
1365  ostr.precision( 3 );
1366 
1367  for ( Size ii = 0; ii < ndims[ 1 ]; ++ii ) {
1368  bin[ 1 ] = ii;
1369  for ( Size jj = 0; jj < ndims[ 2 ]; ++jj ) {
1370  bin[ 2 ] = jj;
1371  for ( Size kk = 0; kk < ndims[ 3 ]; ++kk ) {
1372  bin[ 3 ] = kk;
1373 
1374  if ( ! grid.occupied( bin ) ) continue;
1375 
1376  bool skip = ( skip_completely_buried_positions_ );
1377  if ( skip ) {
1378  if ( bin[ 1 ] == 0 || bin[ 2 ] == 0 || bin[ 3 ] == 0 ) skip = false;
1379  if ( bin[ 1 ] + 1 >= ndims[ 1 ] || bin[ 2 ] + 1 >= ndims[ 2 ] || bin[ 3 ] + 1 >= ndims[ 3 ] ) skip = false;
1380  }
1381  if ( skip ) {
1382  Bin3D neighb;
1383  for ( Size ll = 0; ll <= 2; ++ll ) {
1384  neighb[ 1 ] = bin[ 1 ] - 1 + ll;
1385  for ( Size mm = 0; mm <= 2; ++mm ) {
1386  neighb[ 2 ] = bin[ 2 ] - 1 + mm;
1387  for ( Size nn = 0; nn <= 2; ++nn ) {
1388  neighb[ 3 ] = bin[ 3 ] - 1 + nn;
1389  if ( ll == 1 && mm == 1 && nn == 1 ) continue;
1390  if ( ! grid.occupied( neighb ) ) {
1391  skip = false;
1392  break;
1393  }
1394  }
1395  if ( ! skip ) break;
1396  }
1397  if ( ! skip ) break;
1398  }
1399  }
1400  /// All 27 of this voxel's neighbors are occupied.
1401  if ( skip ) continue;
1402 
1403  Bool3DGrid::CornerPoints c = grid.corners( bin );
1404  for ( Size ll = 1; ll <= 8; ++ll ) c[ ll ] += corner_offsets[ ll ];
1405 
1406  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1407  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1408  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1409  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1410  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1411  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1412  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1413  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1414  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1415  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1416  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1417  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1418  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1419  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1420  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1421  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1422 
1423  }
1424  }
1425  }
1426 
1427  if ( write_empty_voxels_ ) {
1428  ostr << "@vectorlist {} color= " << empty_voxel_color_ << " master= {empty voxels} width= 1\n";
1429  for ( Size ii = 0; ii < ndims[ 1 ]; ++ii ) {
1430  bin[ 1 ] = ii;
1431  for ( Size jj = 0; jj < ndims[ 2 ]; ++jj ) {
1432  bin[ 2 ] = jj;
1433  for ( Size kk = 0; kk < ndims[ 3 ]; ++kk ) {
1434  bin[ 3 ] = kk;
1435  if ( grid.occupied( bin ) ) continue;
1436 
1437  Bool3DGrid::CornerPoints c = grid.corners( bin );
1438  for ( Size ll = 1; ll <= 8; ++ll ) c[ ll ] += corner_offsets[ ll ];
1439 
1440  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1441  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1442  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1443  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1444  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1445  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1446  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1447  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1448  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1449  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1450  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1451  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1452  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1453  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1454  ostr << "{\"}P" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1455  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1456 
1457  }
1458  }
1459  }
1460  }
1461 
1462  if ( write_facets_ ) {
1463 
1464  for ( Size ii = 0; ii < ndims[ 1 ]; ++ii ) {
1465  bin[ 1 ] = ii;
1466  for ( Size jj = 0; jj < ndims[ 2 ]; ++jj ) {
1467  bin[ 2 ] = jj;
1468  for ( Size kk = 0; kk < ndims[ 3 ]; ++kk ) {
1469  bin[ 3 ] = kk;
1470  if ( ! grid.occupied( bin ) ) continue;
1471 
1472  Bool3DGrid::CornerPoints c = grid.corners( bin );
1473  for ( Size ll = 1; ll <= 8; ++ll ) c[ ll ] += corner_offsets[ ll ];
1474  ostr << "@ribbonlist {} color= " << facet_color_ << " master= {" << facet_master_ << "} ";
1475  if ( transparent_facets_ ) ostr << " alpha= " << facet_alpha_ << " ";
1476  ostr << "\n";
1477 
1478  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1479  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1480  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1481  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1482  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1483  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1484  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1485  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1486  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1487  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1488 
1489  ostr << "@ribonlist {} color= " << facet_color_ << " master= {" << facet_master_ << "} ";
1490  if ( transparent_facets_ ) ostr << " alpha= " << facet_alpha_ << " ";
1491  ostr << "\n";
1492 
1493  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[E].x() << " " << c[E].y() << " " << c[E].z() << "\n";
1494  ostr << "{\"} " << ( unselectable_ ? " U ": " " ) << c[H].x() << " " << c[H].y() << " " << c[H].z() << "\n";
1495  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[F].x() << " " << c[F].y() << " " << c[F].z() << "\n";
1496  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[G].x() << " " << c[G].y() << " " << c[G].z() << "\n";
1497 
1498  ostr << "@ribonlist {} color= " << facet_color_ << " master= {" << facet_master_ << "} ";
1499  if ( transparent_facets_ ) ostr << " alpha= " << facet_alpha_ << " ";
1500  ostr << "\n";
1501 
1502  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[A].x() << " " << c[A].y() << " " << c[A].z() << "\n";
1503  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[B].x() << " " << c[B].y() << " " << c[B].z() << "\n";
1504  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[D].x() << " " << c[D].y() << " " << c[D].z() << "\n";
1505  ostr << "{\"}" << ( unselectable_ ? " U ": " " ) << c[C].x() << " " << c[C].y() << " " << c[C].z() << "\n";
1506 
1507  }
1508  }
1509  }
1510 
1511  }
1512 
1513 }
1514 
1515 
1517  std::string const & /*fname*/,
1518  std::string const & /*group_name*/,
1519  Bool3DGrid const & /*grid*/
1520 ) const
1521 {
1522 
1523 }
1524 
1525 /*
1526 private:
1527  bool unselectable_;
1528  std::string line_color_
1529  std::string master_;
1530  Real shrink_factor_;
1531 
1532 
1533  bool write_empty_voxels_;
1534  std::string empty_voxel_color_;
1535 
1536  bool write_facets_;
1537  std::string facet_master_;
1538  std::string facet_color_;
1539  bool transparent_facets_;
1540  Real facet_alpha_;
1541 */
1542 
1543 
1544 }
1545 }