Click here to Skip to main content
15,896,912 members
Articles / Programming Languages / C#

Drawing Component to build GIS and CAM applications

Rate me:
Please Sign up or sign in to vote.
4.72/5 (14 votes)
21 Nov 20055 min read 108K   8K   123  
An object oriented drawing component for building GIS and CAM applications with multiple views of geometrical model, multiple resolution handling, layers, optimized graphics and more.
// This is the main DLL file.

#include "stdafx.h"

#include "GdalImage.h"
#using <System.dll> 
#using <System.Drawing.DLL> 
#include <gdal_priv.h>
//#using <System.Runtime.InteropServices.dll>
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
#include <algorithm>


namespace GdalImage
{
	struct IpRGB
	{
	public:
		unsigned char r;
		unsigned char g;
		unsigned char b;
	};

	bool GeoImage::Open(String* fname)
	{		
		
		char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(fname);
		GDALAllRegister();
		m_poDataset = (GDALDataset *) GDALOpen( str2, GA_ReadOnly );
		
		Marshal::FreeHGlobal(str2);
		if( m_poDataset == NULL )
		{	
			return false;
		}
	
		double  adfGeoTransform[6];

		if( m_poDataset->GetProjectionRef()  != NULL )
		{
			
		}
		if( m_poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
		{
  
		}
		
		m_width = m_poDataset->GetRasterXSize();
		m_height = m_poDataset->GetRasterYSize();
		
		m_trans = new System::Drawing::Drawing2D::Matrix((float)adfGeoTransform[1],
					(float)adfGeoTransform[2],
					(float)adfGeoTransform[4],
					(float)adfGeoTransform[5],
					(float)adfGeoTransform[0],
					(float)adfGeoTransform[3]);
		
		return true;
	}

	bool GeoImage::Draw(System::Drawing::Graphics* graph,System::Drawing::Drawing2D::Matrix* m)
	{
		if(m_poDataset == NULL)	
			return false;
	
		System::Drawing::PointF src_rect_points __gc[] = new System::Drawing::PointF __gc[2];
		src_rect_points[0] = System::Drawing::PointF(graph->ClipBounds.X,graph->ClipBounds.Y);
		src_rect_points[1] = System::Drawing::PointF(graph->ClipBounds.Right,graph->ClipBounds.Bottom);

		// get inverse transformation of geo coordinates to GUI client :
		System::Drawing::Drawing2D::Matrix* graph_inv_trans = m->Clone();
		graph_inv_trans->Invert();
		
		// get inverse transformation image coordinates to geo coordinates:
		System::Drawing::Drawing2D::Matrix* inv_trans = m_trans->Clone();
		inv_trans->Invert();

		graph_inv_trans->Multiply(inv_trans,
			System::Drawing::Drawing2D::MatrixOrder::Append);

		System::Drawing::Drawing2D::Matrix* img2client_trans = graph_inv_trans->Clone();
		img2client_trans->Invert();

		//System::Drawing::RectangleF* src_rect = new System::Drawing::RectangleF();
		
		System::Drawing::RectangleF  rect = System::Drawing::RectangleF(graph->ClipBounds.X,graph->ClipBounds.Y,
			graph->ClipBounds.Width,graph->ClipBounds.Height); 
	
		System::Drawing::PointF points __gc[] = new System::Drawing::PointF __gc[2];
		
		points[0] = System::Drawing::PointF(rect.Left,rect.Top);
		points[1] = System::Drawing::PointF(rect.Right,rect.Bottom);
		
		graph_inv_trans->TransformPoints(points);
		
		double r_x1 = points[0].X;
		double r_y1 = points[0].Y;
				
		double r_x2 = points[1].X;			
		double r_y2 = points[1].Y;
		
		if(r_x1>r_x2)
			std::swap(r_x1,r_x2);

		bool up_north = false;
		if(r_y1>r_y2)
		{
			up_north = true;
			std::swap(r_y1,r_y2);
		}
	
		if(r_x1<0)
			r_x1 = 0;

		if(r_x2 - r_x1 > m_width)
			r_x2 = r_x1 + m_width;

		if(r_y1 < 0)
			r_y1 = 0;

		if(r_y2 - r_y1 > m_height)
			r_y2 = r_y1 + m_height;

		if(r_y2 - r_y1 < 2 || r_x2-r_x1 < 2)
			return false;

		System::Drawing::PointF client_points __gc[] = new System::Drawing::PointF __gc[2];
		
		client_points[0] = System::Drawing::PointF(r_x1,r_y1);
		client_points[1] = System::Drawing::PointF(r_x2,r_y2);
	
		img2client_trans->TransformPoints(client_points);
		int draw_x_size = (int)Math::Abs(client_points[1].X-client_points[0].X);
		int draw_y_size = (int)Math::Abs(client_points[1].Y-client_points[0].Y);
		
		if( draw_x_size < 4 || draw_y_size < 4 )
			return false;

		System::Drawing::Bitmap* bmp = new System::Drawing::Bitmap(draw_x_size,draw_y_size);		
		GDALRasterBand*  poBands[3];

		for(int i=0; i<3; i++) {

			GDALRasterBand  *poBand;
		    int             nBlockXSize, nBlockYSize;
	        int             bGotMin, bGotMax;
	        double          adfMinMax[2];
        
		    poBand = m_poDataset->GetRasterBand( i+1 );
		    poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
		

	       adfMinMax[0] = poBand->GetMinimum( &bGotMin );
	       adfMinMax[1] = poBand->GetMaximum( &bGotMax );
	       if( ! (bGotMin && bGotMax) )
	           GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
	      
		poBands[i] = poBand;
	}

	float *pafScanline;
    int   nXSize = poBands[0]->GetXSize();

	int x_size = poBands[0]->GetXSize();
	int y_size = poBands[0]->GetYSize();

	
    pafScanline = (float *) CPLMalloc(sizeof(float)*draw_x_size*draw_y_size);
	std::fill(pafScanline,pafScanline+draw_x_size*draw_y_size,100);

	IpRGB* img_buff_rgb = new IpRGB [draw_x_size*draw_y_size];

	for(int ch=0; ch<3; ch++)
	{
		unsigned char* ch_buff = (unsigned char*)img_buff_rgb + ch;
    
		poBands[ch]->RasterIO( GF_Read,r_x1, r_y1, 
							r_x2-r_x1, r_y2-r_y1, 
							pafScanline, 
							draw_x_size, 
							draw_y_size, 
							GDT_Float32, 
							0, 0);

		for(int p=0; p<draw_x_size*draw_y_size; p++, ch_buff+=3)
			*ch_buff = (unsigned char)(pafScanline[p]);		
	}
	
	int p_indx = 0;
	
	if(up_north)
	{
		for(int y=draw_y_size-1; y>=0; y--)
			for(int x=0; x<draw_x_size; x++,p_indx++)
			{						
				System::Drawing::Color col = System::Drawing::Color::FromArgb(img_buff_rgb[p_indx].r,img_buff_rgb[p_indx].g,img_buff_rgb[p_indx].b);				
				bmp->SetPixel(x,y,col);
			}
	}
	else
	{
		for(int y=0; y<draw_y_size; y++)
			for(int x=0; x<draw_x_size; x++,p_indx++)
			{						
				System::Drawing::Color col = System::Drawing::Color::FromArgb(img_buff_rgb[p_indx].r,img_buff_rgb[p_indx].g,img_buff_rgb[p_indx].b);				
				bmp->SetPixel(x,y,col);
			}
	}

		graph->DrawImageUnscaled(bmp,(int)client_points[0].X,(int)client_points[0].Y,
			draw_x_size,draw_y_size); 

		delete [] img_buff_rgb;		
		bmp->Dispose();
		CPLFree(pafScanline);
		return true;
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
Baranovsky Eduard has been a software developer for more then 10 years. He has an experence in image processing, computer graphics and distributed systems design.

Comments and Discussions