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.
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
Post a Comment