vtkGeoAlignedImageRepresentation.cxx 7.85 KB
Newer Older
1
/*=========================================================================
Ken Martin's avatar
Ken Martin committed
2 3 4 5 6 7 8 9 10 11 12 13

  Program:   Visualization Toolkit
  Module:    vtkGeoAlignedImageRepresentation.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

14
=========================================================================*/
Ken Martin's avatar
Ken Martin committed
15 16 17 18 19 20 21 22
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkGeoAlignedImageRepresentation.h"

23
#include "vtkCollection.h"
24
#include "vtkGeoImageNode.h"
25
#include "vtkGeoSource.h"
26
#include "vtkGeoTreeNodeCache.h"
27
#include "vtkImageData.h"
Ken Martin's avatar
Ken Martin committed
28
#include "vtkObjectFactory.h"
29 30 31 32 33 34 35
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTexture.h"
#include "vtkTransform.h"
#include "vtkXMLImageDataReader.h"
#include "vtkXMLImageDataWriter.h"

36 37 38
#include <sstream>
#include <stack>
#include <utility>
39

40
static std::pair<vtkGeoImageNode*, double>
41
vtkGeoAlignedImageRepresentationFind(vtkGeoSource* source, vtkGeoImageNode* p, double* bounds, vtkGeoTreeNodeCache* nodeList)
42
{
43
  if (!p->HasData())
44
  {
45
    return std::make_pair(static_cast<vtkGeoImageNode*>(nullptr), 0.0);
46
  }
47 48 49 50 51 52 53 54 55 56 57 58
  double lb[3];
  double ub[3];
  p->GetTexture()->GetImageDataInput(0)->GetOrigin(lb);
  p->GetTexture()->GetImageDataInput(0)->GetSpacing(ub);
  double bcenter[2] = {(bounds[0] + bounds[1])/2.0, (bounds[2] + bounds[3])/2.0};
  double ncenter[2] = {(lb[0] + ub[0])/2.0, (lb[1] + ub[1])/2.0};
  double vec[2] = {bcenter[0] - ncenter[0], bcenter[1] - ncenter[1]};
  double dist2 = vec[0]*vec[0] + vec[1]*vec[1];
  if (lb[0] <= bounds[0] &&
      ub[0] >= bounds[1] &&
      lb[1] <= bounds[2] &&
      ub[1] >= bounds[3])
59
  {
60
    nodeList->SendToFront(p);
61
    std::pair<vtkGeoImageNode*, double> minDist(static_cast<vtkGeoImageNode *>(nullptr), VTK_DOUBLE_MAX);
62 63

    vtkGeoImageNode* child = p->GetChild(0);
64
    vtkCollection* coll = nullptr;
65

66
    if (!child || !child->HasData() || p->GetStatus() == vtkGeoTreeNode::PROCESSING)
67
    {
68
      // TODO: This multiplier should be configurable
69
      if ((ub[0] - lb[0]) > 2.0*(bounds[1] - bounds[0]))
70
      {
71 72 73
        // Populate the children
        coll = source->GetRequestedNodes(p);
        if (coll && coll->GetNumberOfItems() == 4)
74
        {
75
          if (!child)
76
          {
77
            p->CreateChildren();
78
          }
79
          for (int c = 0; c < 4; ++c)
80
          {
81 82
            vtkGeoImageNode* node = vtkGeoImageNode::SafeDownCast(coll->GetItemAsObject(c));
            if (node)
83
            {
84 85 86 87
              p->GetChild(c)->SetImage(node->GetImage());
              p->GetChild(c)->SetTexture(node->GetTexture());
              p->GetChild(c)->SetId(node->GetId());
              p->GetChild(c)->SetLevel(node->GetLevel());
88
              nodeList->SendToFront(p->GetChild(c));
89
            }
90
          }
91 92
          p->SetStatus(vtkGeoTreeNode::NONE);
        }
93
        if (coll)
94
        {
95
          coll->Delete();
96
        }
97
        else if(p->GetStatus() == vtkGeoTreeNode::NONE)
98
        {
99
          p->SetStatus(vtkGeoTreeNode::PROCESSING);
100 101 102 103
          vtkGeoImageNode * temp = vtkGeoImageNode::New();
          temp->DeepCopy(p);
          source->RequestChildren(temp);
          //source->RequestChildren(p);
104
        }
105
      }
106
    }
107 108

    if (p->GetChild(0))
109
    {
110
      for (int i = 0; i < 4; ++i)
111
      {
112
        std::pair<vtkGeoImageNode*, double> subsearch =
113
          vtkGeoAlignedImageRepresentationFind(source, p->GetChild(i), bounds, nodeList);
114
        if (subsearch.first && subsearch.second < minDist.second)
115
        {
116
          minDist = subsearch;
117 118
        }
      }
119
    }
120
    if (minDist.first)
121
    {
122
      return minDist;
123
    }
124 125
    return std::make_pair(p, dist2);
  }
126
  else
127
  {
128
    return std::make_pair(static_cast<vtkGeoImageNode*>(nullptr), 0.0);
129
  }
130 131
}

132 133 134 135
vtkStandardNewMacro(vtkGeoAlignedImageRepresentation);
vtkCxxSetObjectMacro(vtkGeoAlignedImageRepresentation, GeoSource, vtkGeoSource);
//----------------------------------------------------------------------------
vtkGeoAlignedImageRepresentation::vtkGeoAlignedImageRepresentation()
Ken Martin's avatar
Ken Martin committed
136
{
137
  this->GeoSource = nullptr;
138
  this->Root = vtkGeoImageNode::New();
139
  this->Cache = vtkGeoTreeNodeCache::New();
140
  this->SetNumberOfInputPorts(0);
Ken Martin's avatar
Ken Martin committed
141 142
}

143 144
//----------------------------------------------------------------------------
vtkGeoAlignedImageRepresentation::~vtkGeoAlignedImageRepresentation()
Ken Martin's avatar
Ken Martin committed
145
{
146
  this->SetGeoSource(nullptr);
147
  if (this->Root)
148
  {
149
    this->Root->Delete();
150
  }
151
  if (this->Cache)
152
  {
153
    this->Cache->Delete();
154
  }
Ken Martin's avatar
Ken Martin committed
155 156
}

157 158
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::SetSource(vtkGeoSource* source)
159
{
160
  if (this->GeoSource != source)
161
  {
162 163
    this->SetGeoSource(source);
    if (this->GeoSource)
164
    {
165
      this->Initialize();
166
    }
167
  }
168 169
}

170 171
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::Initialize()
172
{
173
  if (!this->GeoSource)
174
  {
175 176
    vtkErrorMacro(<< "You must set the source before initialization.");
    return;
177
  }
178
  this->GeoSource->FetchRoot(this->Root);
179 180
}

181 182
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::SaveDatabase(const char* path)
183
{
184
  if (!this->Root)
185
  {
186
    this->Initialize();
187
  }
188
  std::stack< vtkSmartPointer<vtkGeoImageNode> > s;
189 190
  s.push(this->Root);
  while (!s.empty())
191
  {
192 193
    vtkSmartPointer<vtkGeoImageNode> node = s.top();
    s.pop();
194

195 196 197 198 199
    // Write out file.
    vtkSmartPointer<vtkImageData> storedImage = vtkSmartPointer<vtkImageData>::New();
    storedImage->ShallowCopy(node->GetTexture()->GetInput());
    vtkSmartPointer<vtkXMLImageDataWriter> writer = vtkSmartPointer<vtkXMLImageDataWriter>::New();
    char fn[512];
200
    snprintf(fn, sizeof(fn), "%s/tile_%d_%ld.vti", path, node->GetLevel(), node->GetId());
201
    writer->SetFileName(fn);
202
    writer->SetInputData(storedImage);
203 204 205 206
    writer->Write();

    // Recurse over children.
    for (int i = 0; i < 4; ++i)
207
    {
208 209 210
      vtkSmartPointer<vtkGeoImageNode> child =
        vtkSmartPointer<vtkGeoImageNode>::New();
      if (this->GeoSource->FetchChild(node, i, child))
211
      {
212 213
        // Skip nodes outside range of the world.
        if (child->GetLatitudeRange()[1] > -90.0)
214
        {
215
          s.push(child);
216 217 218
        }
      }
    }
219
  }
220 221
}

222 223
//----------------------------------------------------------------------------
vtkGeoImageNode* vtkGeoAlignedImageRepresentation::GetBestImageForBounds(double bounds[4])
224
{
225
  std::pair<vtkGeoImageNode*, double> res =
226
    vtkGeoAlignedImageRepresentationFind(this->GeoSource, this->Root, bounds, this->Cache);
227
  return res.first;
228 229
}

230 231
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::PrintSelf(ostream& os, vtkIndent indent)
232
{
233
  this->PrintTree(os, indent, this->Root);
234 235
}

236 237
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::PrintTree(ostream& os, vtkIndent indent, vtkGeoImageNode* root)
238
{
239 240 241 242 243
  os << indent << "Id: " << root->GetId() << endl;
  os << indent << "LatitudeRange: " << root->GetLatitudeRange()[0] << ", " << root->GetLatitudeRange()[1] << endl;
  os << indent << "LongitudeRange: " << root->GetLongitudeRange()[0] << ", " << root->GetLongitudeRange()[1] << endl;
  os << indent << "Level: " << root->GetLevel() << endl;
  if (root->GetChild(0))
244
  {
245
    for (int i = 0; i < 4; ++i)
246
    {
247
      this->PrintTree(os, indent.GetNextIndent(), root->GetChild(i));
248
    }
249
  }
250
}