bool Pset_to_cgrid_copier::copy( const Geostat_grid* server, 
                                 const Grid_continuous_property* server_prop,
                                 Geostat_grid* client, 
                                 Grid_continuous_property* client_prop ) {
  Cartesian_grid* cgrid = dynamic_cast< Cartesian_grid* >( client );
  const Point_set* pset = dynamic_cast< const Point_set* >( server );

  if( !cgrid || !pset ) return false;

  typedef Grid_continuous_property::property_type Property_type;

  copy_categorical_definition(server_prop,client_prop);

  // check if we already worked with "source" and "property_name" 
  // If that's the case and we're not required to do the assignement
  // from scratch, use what we did last time.
  if( !from_scratch_ && server == server_ &&
      server_prop == server_prop_ && client == client_ ) {
    
    for( unsigned int i = 0 ; i < last_assignement_.size() ; i++ ) {
      Property_type val = server_prop->get_value( last_assignement_[i].first );
      client_prop->set_value( val, last_assignement_[i].second );
      if( mark_as_hard_ )
      	client_prop->set_harddata( true, last_assignement_[i].second );
    } 
    return true;
  }
  
  last_assignement_.clear();
  backup_.clear();
  server_ = server;
  server_prop_ = server_prop;
  client_ = client;
  client_property_ = client_prop;

  typedef Point_set::location_type location_type;
  typedef std::vector<location_type> Location_vector;
  typedef std::vector<location_type>::const_iterator const_iterator;

  // We will need to obtain the coordinates of a grid node from its
  // node id. Hence we need a grid-cursor, set to multigrid level 1.
  SGrid_cursor cursor = *( cgrid->cursor() );
  cursor.set_multigrid_level( 1 );

  const Location_vector& locations = pset->point_locations();

  GsTL_cube bbox = cgrid->bounding_box();
  GsTLInt current_id = 0;

  // Use a map to record what point was assigned to which grid node
  // This map is used in case multiple points could be assigned to the
  // same grid node: in that case the new point is assigned if it is closer
  // to the grid node than the previously assigned node was.
  typedef std::map<GsTLInt,location_type>::iterator map_iterator;
  std::map<GsTLInt,location_type> already_assigned;

  overwrite_ = true;   // added by Jianbing Wu, 03/20/2006

  for( const_iterator loc_ptr = locations.begin(); loc_ptr != locations.end(); 
       ++loc_ptr, current_id++ ) {

    if( !server_prop->is_informed( current_id ) ) continue;

    // only consider the points inside the target's bounding box
    if( !bbox.contains( *loc_ptr ) ) continue;


    GsTLInt node_id = cgrid->closest_node( *loc_ptr );
    appli_assert( node_id >=0 && node_id < client_prop->size() );
    appli_assert( current_id < server_prop->size() );

    // If there is already a property value (not assigned by the
    // grid initializer), and we don't want to overwrite, leave it alone
    if( !overwrite_ && client_prop->is_informed( node_id ) ) continue;

//    bool perform_assignment = true;

    // check if a point was already assigned to that node
    map_iterator it = already_assigned.find( node_id );
    if( it != already_assigned.end() ) {
    	int i,j,k;
    	GsTLCoordVector sizes = cgrid->cell_dimensions();
     	cursor.coords( node_id, i,j,k );
     	location_type node_loc( float(i)*sizes.x(),
			                        float(j)*sizes.y(),
			                        float(k)*sizes.z() );

     	// if the new point is further away to the grid node than
     	// the already assigned node, don't assign the new point
     	if( square_euclidean_distance( node_loc, *loc_ptr ) > 
          square_euclidean_distance( node_loc, it->second ) ) 
        continue; //perform_assignment = false;
    }

//    if( perform_assignment ) {
  	// store the node id of the source and of the target and make a backup of the
    // property value of the client property
   	last_assignement_.push_back( std::make_pair( current_id, node_id ) );

    if( !undo_enabled_ ) {
      Property_type backup_val = Grid_continuous_property::no_data_value;
      if( client_prop->is_informed( node_id ) )
        backup_val = client_prop->get_value( node_id );
      backup_.push_back( std::make_pair( node_id, backup_val ) );
    }

    Property_type val = server_prop->get_value( current_id ); 
    client_prop->set_value( val, node_id );
    already_assigned[node_id] = *loc_ptr;
    if( mark_as_hard_ )
        client_prop->set_harddata( true, node_id );

    }

  overwrite_ = false;   // added by Jianbing Wu, 03/20/2006

  unset_harddata_flag_ = mark_as_hard_;
  return true;
}
bool Create_mgrid_from_cgrid::exec(){
  // Get the grid from the manager
  SmartPtr<Named_interface> ni =
    Root::instance()->interface( gridModels_manager + "/" + cgrid_name_ );
  if( ni.raw_ptr() == 0 ) {
    errors_->report( "Object " + cgrid_name_ + " does not exist." );
    return false;
  }

  Cartesian_grid* cgrid = dynamic_cast<Cartesian_grid*>( ni.raw_ptr() );
  if( cgrid == 0) {
    errors_->report( "Object " + cgrid_name_ + " is not a cartesian grid." );
    return false;
  }    
 // Get the region
  std::vector<Grid_region*> regions;
  std::vector<std::string>::iterator it =  region_names_.begin();
  for( ; it!= region_names_.end(); ++it) {
    Grid_region* region = cgrid->region( *it );
    if(!region) {
      errors_->report( "Region " + (*it) + " does not exist."  );
      return false;
    }
    regions.push_back(region);
  }
  
// Create the new masked_grid

  ni = 
      Root::instance()->new_interface("reduced_grid://"+mgrid_name_,
      gridModels_manager + "/" + mgrid_name_);
 
  if( ni.raw_ptr() == 0 ) {
    errors_->report( "Object " + mgrid_name_ + " already exists. Use a different name." );
    return false;
  }
  
  Reduced_grid* grid = dynamic_cast<Reduced_grid*>( ni.raw_ptr() );

  //Create the grid
  if( regions.size() == 1 ) {  //avoid a copy of the region array
    grid->set_dimensions( 
      cgrid->geometry()->dim(0), 
      cgrid->geometry()->dim(1), 
      cgrid->geometry()->dim(2),
      cgrid->cell_dimensions()[0], 
      cgrid->cell_dimensions()[1], 
      cgrid->cell_dimensions()[2], 
      regions[0]->data(),
      cgrid->rotation_z());
  } else {
    int mask_size = regions[0]->size();
    std::vector<bool> mask( mask_size );
    for( int i=0; i< mask_size; ++i ) {
      bool ok = false;
      for( int j = 0; j<regions.size(); j++ ) {
        ok == ok || regions[j]->is_inside_region(i);
      }
      mask[i] = ok;
    }
    grid->set_dimensions( 
      cgrid->geometry()->dim(0), 
      cgrid->geometry()->dim(1), 
      cgrid->geometry()->dim(2),
      cgrid->cell_dimensions()[0], 
      cgrid->cell_dimensions()[1], 
      cgrid->cell_dimensions()[2], 
      mask,
      cgrid->rotation_z());
  }

  grid->origin( cgrid->origin() );

  proj_->new_object( mgrid_name_ );
  return true;
}