Skip to main content

Tooltopia

Part of recent events I've been busy on a streaming module of terrain rendering allowing an virtually unlimited terrain. While this is trivial there is still a problem of getting content. Luckily there are published elevation files,  SMRT or  it's predecessor DEM, from earth's key locations e.g. Taiwan. To process elevation information we do what we engineers do best, write tools.




I decided to step out of my comfort box and give C++CLI a shot.  Despite what people say mixed-mode assembly capabilities of C++CLI is quite a nice. We get to write all the goodies of .net exception being pretty syntax, and  we get to have low-level memory accessibility. It is truly ideal for some quick visualizations  without the need of going through the standard project setup workflow: downloading boost, downloading Qt, compiling them, add in some other third party libraries, reinvent code.
private: System::Void loadToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
  System::Windows::Forms::OpenFileDialog^ dialog = gcnew System::Windows::Forms::OpenFileDialog();
  dialog->Filter = "SRTM (*.hgt)|*.hgt";
  dialog->Multiselect = true;

  float minAltitude = -62;
  float maxAltitude = 3811;
  float altitudeRange = maxAltitude - minAltitude;

  if( dialog->ShowDialog() == System::Windows::Forms::DialogResult::OK )
  {

  System::Drawing::Color ocean = System::Drawing::Color::FromArgb(255, 60, 80, 100);
  System::Drawing::Bitmap^ gradiant = gcnew System::Drawing::Bitmap(1,1024, System::Drawing::Imaging::PixelFormat::Format32bppArgb);
  if( gradiant != nullptr  )
  {
   System::Drawing::Drawing2D::LinearGradientBrush^ brush = gcnew System::Drawing::Drawing2D::LinearGradientBrush(
    System::Drawing::Rectangle(0,0,1,1024), System::Drawing::Color::Black, System::Drawing::Color::White,
    System::Drawing::Drawing2D::LinearGradientMode::Vertical);

   System::Drawing::Drawing2D::ColorBlend^ blend = gcnew System::Drawing::Drawing2D::ColorBlend();
   blend->Positions = gcnew cli::array<float>(14);
   blend->Colors = gcnew cli::array<System::Drawing::Color>(14);
   blend->Positions[ 0] =(  -62 - minAltitude) / altitudeRange; blend->Colors[ 0] = System::Drawing::Color::FromArgb(255, 139, 146, 112);
   blend->Positions[ 1] =(  284 - minAltitude) / altitudeRange; blend->Colors[ 1] = System::Drawing::Color::FromArgb(255, 158, 159, 117);
   blend->Positions[ 2] =(  578 - minAltitude) / altitudeRange; blend->Colors[ 2] = System::Drawing::Color::FromArgb(255, 177, 173, 123);
   blend->Positions[ 3] =(  872 - minAltitude) / altitudeRange; blend->Colors[ 3] = System::Drawing::Color::FromArgb(255, 196, 186, 129);
   blend->Positions[ 4] =( 1166 - minAltitude) / altitudeRange; blend->Colors[ 4] = System::Drawing::Color::FromArgb(255, 215, 200, 135);
   blend->Positions[ 5] =( 1460 - minAltitude) / altitudeRange; blend->Colors[ 5] = System::Drawing::Color::FromArgb(255, 208, 190, 128);
   blend->Positions[ 6] =( 1754 - minAltitude) / altitudeRange; blend->Colors[ 6] = System::Drawing::Color::FromArgb(255, 202, 180, 121);
   blend->Positions[ 7] =( 2048 - minAltitude) / altitudeRange; blend->Colors[ 7] = System::Drawing::Color::FromArgb(255, 195, 170, 114);
   blend->Positions[ 8] =( 2342 - minAltitude) / altitudeRange; blend->Colors[ 8] = System::Drawing::Color::FromArgb(255, 189, 160, 107);
   blend->Positions[ 9] =( 2636 - minAltitude) / altitudeRange; blend->Colors[ 9] = System::Drawing::Color::FromArgb(255, 183, 150, 101);
   blend->Positions[10] =( 2930 - minAltitude) / altitudeRange; blend->Colors[10] = System::Drawing::Color::FromArgb(255, 179, 154, 113);
   blend->Positions[11] =( 3224 - minAltitude) / altitudeRange; blend->Colors[11] = System::Drawing::Color::FromArgb(255, 175, 158, 126);
   blend->Positions[12] =( 3518 - minAltitude) / altitudeRange; blend->Colors[12] = System::Drawing::Color::FromArgb(255, 171, 162, 138);
   blend->Positions[13] =( 3811 - minAltitude) / altitudeRange; blend->Colors[13] = System::Drawing::Color::FromArgb(255, 167, 167, 151);
   brush->InterpolationColors = blend;

   System::Drawing::Graphics^ g = System::Drawing::Graphics::FromImage(gradiant);
   g->FillRectangle( brush, System::Drawing::Rectangle(0,0,1,1024));
   delete g;
  }

  int minLongitude = 0x7FFFFFFF, maxLongitude = 0xFFFFFFFF;
  int minLatitude = 0x7FFFFFFF, maxLatitude = 0xFFFFFFFF;
     System::Text::RegularExpressions::Regex^ regex = gcnew System::Text::RegularExpressions::Regex("(N|S)(d+)(E|W)(d+).hgt");
  for( int i = 0; i < dialog->FileNames->Length; i++ )
  {
   System::Text::RegularExpressions::Match^ matches = regex->Match( dialog->FileNames[i] );
   System::IO::FileInfo^ info = gcnew System::IO::FileInfo( dialog->FileNames[i] );
   int numberOfEntries = (info->Length / 2), gridSize = System::Math::Sqrt( numberOfEntries );
   int latitude = System::Int32::Parse( matches->Groups[2]->Value );
   int longitude = System::Int32::Parse( matches->Groups[4]->Value );
   minLatitude = System::Math::Min( minLatitude, latitude );
   maxLatitude = System::Math::Max( maxLatitude, latitude + 1 );
   minLongitude = System::Math::Min( minLongitude, longitude );
   maxLongitude = System::Math::Max( maxLongitude, longitude + 1 );
  }

  int numberOfBlocksWidth = maxLongitude - minLongitude;
  int numberOfBlocksHeight = maxLatitude - minLatitude;
  int pixelsWidth = (numberOfBlocksWidth * 1201);
  int pixelsHeight = (numberOfBlocksHeight * 1201);

  cli::array<signed short,2>^ values = gcnew cli::array<signed short,2>(pixelsWidth, pixelsHeight);
  for( int y = 0; y < pixelsHeight; y++ ) for( int x = 0; x < pixelsWidth; x++ )
   values[x,y] = -100;

  System::Drawing::Bitmap^ bitmap = gcnew System::Drawing::Bitmap(pixelsWidth,pixelsHeight, System::Drawing::Imaging::PixelFormat::Format32bppArgb );
  System::Drawing::Graphics^ g = System::Drawing::Graphics::FromImage(bitmap);
  g->Clear( ocean );
  delete g;

  for( int i = 0; i < dialog->FileNames->Length; i++ )
  {
   System::Text::RegularExpressions::Match^ matches = regex->Match( dialog->FileNames[i] );
   System::IO::FileStream^ fs = System::IO::File::OpenRead(dialog->FileNames[i]);
   int latitude = System::Int32::Parse( matches->Groups[2]->Value );
   int longitude = System::Int32::Parse( matches->Groups[4]->Value );
   int length = fs->Length / 2, gsize= System::Math::Sqrt( length );

   int pixelOffsetX = gsize * (longitude - minLongitude), pixelOffsetY = gsize * (latitude - minLatitude);
   //pixelOffsetX = pixelsWidth - gsize - pixelOffsetX;
   pixelOffsetY = pixelsHeight - gsize - pixelOffsetY;

   System::Drawing::Imaging::BitmapData^ data = bitmap->LockBits(  System::Drawing::Rectangle(pixelOffsetX,pixelOffsetY,gsize,gsize), System::Drawing::Imaging::ImageLockMode::WriteOnly, System::Drawing::Imaging::PixelFormat::Format32bppArgb );
   for(int y=0; y < gsize; y++)
   {
    System::Byte* row=   (System::Byte*)(data->Scan0.ToPointer() ) + System::Int32(y*data->Stride);
    for(int x=0; x< gsize; x++)
    {     

     signed short value = (fs->ReadByte() << 8) | (fs->ReadByte()  << 0);
     values[pixelOffsetX + x, pixelOffsetY + y] = value;
     signed short valueClamped = System::Math::Max( System::Math::Min( value, (signed short)maxAltitude ), (signed short)minAltitude );
     signed int pixelOffset = (int)((valueClamped - minAltitude) / altitudeRange * 1023.0);
     System::Drawing::Color color = gradiant->GetPixel( 0, pixelOffset);
     if( value <= 0 )  color = ocean;

     row[x * 4 + 0] = color.B;
     row[x * 4 + 1] = color.G;
     row[x * 4 + 2] = color.R;
     row[x * 4 + 3] = 255;
    }
   }

   bitmap->UnlockBits(data );
   fs->Close();
  }       

  pictureBox1->Image = bitmap;
  pictureBox1->Bounds = System::Drawing::Rectangle(0,0, numberOfBlocksWidth * 1201, numberOfBlocksHeight * 1201);
  data_values = values;
  data_size_x = numberOfBlocksWidth * 1201;
  data_size_y = numberOfBlocksHeight * 1201;
  }
 }



Comments

Popular posts from this blog

Material & shader management

In the upcoming changes in my editor I implemented the material system inspired on  Frostbite engine of DICE, binaries are download-able on the project page. Also I've implemented an conversion tool and file-format for future mesh formats using Assimp.

Asian food culture

When you think about Asian foods of course you might be thinking about those famous dishes that have made it into the western society like Sushi, Nasi or Bami.

The 8 Best U.S. Cities to Visit for a Quick Vacation

The best thing about visiting a new city is experiencing the thrill of adventure. From delicious food to rich history, there’s always something new to do. Whether you live close to these cities or you’re planning on making a trip to the USA, here's 8 of the best U.S. cities to visit on your next vacation (in no particular order): 1. Portland, Oregon As Oregon’s largest city, Portland has steadily been on the rise as a hotspot for food and beer connoisseurs. It’s nestled between the Columbia and Willamette Rivers with a stunning view of snowy Mount Hood which only adds to the thriving artistic culture. Portland is also home to beautiful parks, bridges and bike paths, making this city a top choice for outdoor adventurists. If you’re looking for more breathtaking escapades, Portland is nearby to a few national forests including Mount Hood National Forest and Gifford Pinchot National Forest. 2. Nashville, Tennessee Nashville rightfully owns...