1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                    User Interface                     //
9 //                                                       //
10 //                    Program: SAGA                      //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                   WKSP_Map_DC.cpp                     //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'. SAGA is free software; you   //
22 // can redistribute it and/or modify it under the terms  //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the     //
25 // License, or (at your option) any later version.       //
26 //                                                       //
27 // SAGA is distributed in the hope that it will be       //
28 // useful, but WITHOUT ANY WARRANTY; without even the    //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
30 // PARTICULAR PURPOSE. See the GNU General Public        //
31 // License for more details.                             //
32 //                                                       //
33 // You should have received a copy of the GNU General    //
34 // Public License along with this program; if not, see   //
35 // <http://www.gnu.org/licenses/>.                       //
36 //                                                       //
37 //-------------------------------------------------------//
38 //                                                       //
39 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Goettingen               //
42 //                Goldschmidtstr. 5                      //
43 //                37077 Goettingen                       //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include <wx/window.h>
52 
53 #include "helper.h"
54 
55 #include "wksp_map_dc.h"
56 
57 
58 ///////////////////////////////////////////////////////////
59 //														 //
60 //														 //
61 //														 //
62 ///////////////////////////////////////////////////////////
63 
64 //---------------------------------------------------------
CWKSP_Map_DC(const CSG_Rect & rWorld,const wxRect & rDC,double Scale,int Background)65 CWKSP_Map_DC::CWKSP_Map_DC(const CSG_Rect &rWorld, const wxRect &rDC, double Scale, int Background)
66 {
67 	m_rWorld		= rWorld;
68 	m_rDC			= rDC;
69 	m_Scale			= Scale;
70 
71 	m_img_rgb		= NULL;
72 	m_img_dc_rgb	= NULL;
73 
74 	m_Background[0]	= Background >= 0 ? SG_GET_R(Background) : 254;
75 	m_Background[1]	= Background >= 0 ? SG_GET_G(Background) : 255;
76 	m_Background[2]	= Background >= 0 ? SG_GET_B(Background) : 255;
77 
78 	//-----------------------------------------------------
79 	if( m_rWorld.Get_XRange() == 0. || m_rWorld.Get_YRange() == 0. )
80 	{
81 		m_rWorld.Inflate(m_rWorld.Get_XRange() ? 0. : 1., m_rWorld.Get_YRange() ? 0. : 1., false);
82 	}
83 
84 	//-----------------------------------------------------
85 	// ensure cellsize in x-/y-direction are identical...
86 	double	dxdyDC		= (double)m_rDC.GetWidth() / (double)m_rDC.GetHeight();
87 	double	dxdyWorld	= m_rWorld.Get_XRange() / m_rWorld.Get_YRange();
88 
89 	if( dxdyDC > dxdyWorld )
90 	{
91 		m_rWorld.Inflate(0.5 * (m_rWorld.Get_YRange() * dxdyDC - m_rWorld.Get_XRange()), 0., false);
92 	}
93 	else if( dxdyDC < dxdyWorld )
94 	{
95 		m_rWorld.Inflate(0., 0.5 * (m_rWorld.Get_XRange() / dxdyDC - m_rWorld.Get_YRange()), false);
96 	}
97 
98 	//-----------------------------------------------------
99 	m_World2DC		= (double)m_rDC.GetWidth() / m_rWorld.Get_XRange();
100 	m_DC2World		= 1. / m_World2DC;
101 
102 	//-----------------------------------------------------
103 	dc_BMP.Create(m_rDC.GetWidth(), m_rDC.GetHeight());
104 	dc.SelectObject(dc_BMP);
105 	dc.SetBackground(wxBrush(wxColour(m_Background[0], m_Background[1], m_Background[2]), wxBRUSHSTYLE_SOLID));
106 	dc.Clear();
107 }
108 
109 //---------------------------------------------------------
~CWKSP_Map_DC(void)110 CWKSP_Map_DC::~CWKSP_Map_DC(void)
111 {}
112 
113 
114 ///////////////////////////////////////////////////////////
115 //														 //
116 ///////////////////////////////////////////////////////////
117 
118 //---------------------------------------------------------
Draw(wxDC & dc_Target)119 void CWKSP_Map_DC::Draw(wxDC &dc_Target)
120 {
121 	dc.SelectObject(wxNullBitmap);
122 
123 	dc_Target.DrawBitmap(dc_BMP, m_rDC.GetLeft(), m_rDC.GetTop(), false);
124 }
125 
126 
127 ///////////////////////////////////////////////////////////
128 //														 //
129 ///////////////////////////////////////////////////////////
130 
131 //---------------------------------------------------------
Draw_DC(CWKSP_Map_DC & dc_Source,double Transparency)132 void CWKSP_Map_DC::Draw_DC(CWKSP_Map_DC &dc_Source, double Transparency)
133 {
134 	if( IMG_Draw_Begin(Transparency) )
135 	{
136 		wxImage src_img	= dc_Source.dc_BMP.ConvertToImage(); if( !src_img.GetData() ) { return; }
137 
138 		#pragma omp parallel for
139 		for(int y=0; y<m_rDC.GetHeight(); y++)
140 		{
141 			int	i = y * 3 * m_rDC.GetWidth(); BYTE *src_rgb	= src_img.GetData() + i;
142 
143 			for(int x=0; x<m_rDC.GetWidth(); x++, i+=3, src_rgb+=3)
144 			{
145 				if( src_rgb[0] != dc_Source.m_Background[0]
146 				||  src_rgb[1] != dc_Source.m_Background[1]
147 				||  src_rgb[2] != dc_Source.m_Background[2] )
148 				{
149 					IMG_Set_Pixel_Direct(i, *((int *)src_rgb));
150 				}
151 			}
152 		}
153 
154 		IMG_Draw_End();
155 	}
156 }
157 //{
158 //	wxImage dst_img	=           dc_BMP.ConvertToImage();
159 //	wxImage src_img	= dc_Source.dc_BMP.ConvertToImage();
160 //
161 //	//-----------------------------------------------------
162 //	#pragma omp parallel for
163 //	for(int y=0; y<m_rDC.GetHeight(); y++)
164 //	{
165 //		BYTE   *src_rgb	= src_img.GetData() + y * 3 * m_rDC.GetWidth();
166 //		BYTE   *dst_rgb	= dst_img.GetData() + y * 3 * m_rDC.GetWidth();
167 //
168 //		for(int x=0; x<m_rDC.GetWidth(); x++, src_rgb+=3, dst_rgb+=3)
169 //		{
170 //			if( src_rgb[0] != dc_Source.m_Background[0]
171 //			||  src_rgb[1] != dc_Source.m_Background[1]
172 //			||  src_rgb[2] != dc_Source.m_Background[2] )
173 //			{
174 //				dst_rgb[0]	= (int)((1. - Transparency) * src_rgb[0] + Transparency * dst_rgb[0]);
175 //				dst_rgb[1]	= (int)((1. - Transparency) * src_rgb[1] + Transparency * dst_rgb[1]);
176 //				dst_rgb[2]	= (int)((1. - Transparency) * src_rgb[2] + Transparency * dst_rgb[2]);
177 //			}
178 //		}
179 //	}
180 //
181 //	//-----------------------------------------------------
182 //	dc.DrawBitmap(wxBitmap(dst_img), 0, 0, true);
183 //}
184 
185 
186 ///////////////////////////////////////////////////////////
187 //														 //
188 ///////////////////////////////////////////////////////////
189 
190 //---------------------------------------------------------
Set_Font(wxFont & Font)191 void CWKSP_Map_DC::Set_Font(wxFont &Font)
192 {
193 	if( Font.Ok() )
194 	{
195 		Font.SetPointSize((int)(m_Scale * Font.GetPointSize()));
196 
197 		dc.SetFont(Font);
198 	}
199 }
200 
201 
202 ///////////////////////////////////////////////////////////
203 //														 //
204 ///////////////////////////////////////////////////////////
205 
206 //---------------------------------------------------------
IMG_Draw_Begin(double Transparency,int Mode)207 bool CWKSP_Map_DC::IMG_Draw_Begin(double Transparency, int Mode)
208 {
209 	if( m_DC2World <= 0. || m_rDC.GetWidth() <= 0 || m_rDC.GetHeight() <= 0 )
210 	{
211 		return( false );
212 	}
213 
214 	m_Opacity	= Transparency < 0. ? 1. : Transparency > 1. ? 0. : 1. - Transparency;
215 
216 	if( m_Opacity <= 0. && (Mode == IMG_MODE_TRANSPARENT || Mode == IMG_MODE_TRANSPARENT_ALPHA) )
217 	{
218 		return( false );
219 	}
220 
221 	switch( Mode )
222 	{
223 	case IMG_MODE_OPAQUE:   default: m_img_mode = IMG_MODE_OPAQUE                                        ; break;
224 	case IMG_MODE_SHADING          : m_img_mode = IMG_MODE_SHADING                                       ; break;
225 	case IMG_MODE_TRANSPARENT      : m_img_mode = m_Opacity < 1. ? IMG_MODE_TRANSPARENT : IMG_MODE_OPAQUE; break;
226 	case IMG_MODE_TRANSPARENT_ALPHA: m_img_mode = IMG_MODE_TRANSPARENT_ALPHA                             ; break;
227 	}
228 
229 	//-----------------------------------------------------
230 	m_img.Create(m_rDC.GetWidth(), m_rDC.GetHeight());
231 	m_img.SetMask(true);
232 	m_img.SetMaskColour(m_Background[0], m_Background[1], m_Background[2]);
233 	m_img_rgb		= m_img.GetData();
234 	m_img_nx		= m_rDC.GetWidth();
235 	m_img_nBytes	= 3 * m_rDC.GetHeight() * m_rDC.GetWidth();
236 
237 	BYTE	*pRGB	= m_img_rgb;
238 
239 	for(int i=0; i<m_img_nBytes; i+=3)
240 	{
241 		*pRGB++	= m_Background[0];
242 		*pRGB++	= m_Background[1];
243 		*pRGB++	= m_Background[2];
244 	}
245 
246 	//-----------------------------------------------------
247 	if( m_img_mode != IMG_MODE_OPAQUE )
248 	{
249 		wxBitmap	tmp_BMP(m_rDC.GetWidth(), m_rDC.GetHeight());
250 		wxMemoryDC	tmp_dc;
251 
252 		tmp_dc.SelectObject(tmp_BMP);
253 		tmp_dc.Blit(0, 0, m_rDC.GetWidth(), m_rDC.GetHeight(), &dc, 0, 0);
254 		tmp_dc.SelectObject(wxNullBitmap);
255 
256 		if( !tmp_BMP.IsOk() )
257 		{
258 			m_img.Destroy();
259 			m_img_rgb		= NULL;
260 			m_img_nx		= 0;
261 			m_img_nBytes	= 0;
262 
263 			return( false );
264 		}
265 
266 		m_img_dc		= tmp_BMP.ConvertToImage();
267 		m_img_dc_rgb	= m_img_dc.GetData();
268 	}
269 
270 	return( true );
271 }
272 
273 //---------------------------------------------------------
IMG_Draw_End(void)274 bool CWKSP_Map_DC::IMG_Draw_End(void)
275 {
276 	if( !m_img.Ok() )
277 	{
278 		return( false );
279 	}
280 
281 	//-----------------------------------------------------
282 	dc.DrawBitmap(wxBitmap(m_img), 0, 0, true);
283 
284 	m_img.Destroy();
285 	m_img_rgb		= NULL;
286 	m_img_nx		= 0;
287 	m_img_nBytes	= 0;
288 
289 	if( m_img_dc.Ok() )
290 	{
291 		m_img_dc.Destroy();
292 		m_img_dc_rgb	= NULL;
293 	}
294 
295 	return( true );
296 }
297 
298 //---------------------------------------------------------
IMG_Set_Rect(int x_a,int y_a,int x_b,int y_b,int Color)299 void CWKSP_Map_DC::IMG_Set_Rect(int x_a, int y_a, int x_b, int y_b, int Color)
300 {
301 	if( y_a >  y_b               ) { double y = y_a; y_a = y_b; y_b = y; }
302 	if( y_a <  0                 ) { y_a = 0; }
303 	if( y_b >= m_rDC.GetHeight() ) { y_b = m_rDC.GetHeight(); }
304 
305 	if( x_a > x_b                ) { double x = x_a; x_a = x_b; x_b = x; }
306 	if( x_a < 0                  ) { x_a = 0; }
307 	if( x_b >= m_rDC.GetWidth () ) { x_b = m_rDC.GetWidth (); }
308 
309 	//-----------------------------------------------------
310 	for(int y=y_a; y<y_b; y++)
311 	{
312 		int	i	= 3 * (y * m_img_nx + x_a);
313 
314 		for(int x=x_a; x<x_b; x++, i+=3)
315 		{
316 			IMG_Set_Pixel_Direct(i, Color);
317 		}
318 	}
319 }
320 
321 
322 ///////////////////////////////////////////////////////////
323 //														 //
324 ///////////////////////////////////////////////////////////
325 
326 //---------------------------------------------------------
Draw_Polygon(CSG_Shape_Polygon * pPolygon)327 void CWKSP_Map_DC::Draw_Polygon(CSG_Shape_Polygon *pPolygon)
328 {
329 	if(	m_World2DC * pPolygon->Get_Extent().Get_XRange() <= 2.
330 	&&	m_World2DC * pPolygon->Get_Extent().Get_YRange() <= 2. )
331 	{
332 		dc.DrawPoint(
333 			(int)xWorld2DC(pPolygon->Get_Extent().Get_XCenter()),
334 			(int)yWorld2DC(pPolygon->Get_Extent().Get_YCenter())
335 		);
336 	}
337 
338 	//-----------------------------------------------------
339 	else if( pPolygon->Get_Part_Count() == 1 && pPolygon->Get_Point_Count(0) > 2 )
340 	{
341 		wxPoint	*Points	= new wxPoint[pPolygon->Get_Point_Count()];
342 
343 		for(int iPoint=0; iPoint<pPolygon->Get_Point_Count(0); iPoint++)
344 		{
345 			Points[iPoint].x = (int)xWorld2DC(pPolygon->Get_Point(iPoint, 0).x);
346 			Points[iPoint].y = (int)yWorld2DC(pPolygon->Get_Point(iPoint, 0).y);
347 		}
348 
349 		dc.DrawPolygon(pPolygon->Get_Point_Count(), Points);
350 
351 		delete[](Points);
352 	}
353 
354 	//-----------------------------------------------------
355 	else if( pPolygon->Get_Part_Count() > 1 )
356 	{
357 		wxPoint  *Points = new wxPoint[pPolygon->Get_Point_Count()];
358 		int     *nPoints = new int    [pPolygon->Get_Part_Count ()];
359 
360 		for(int iPart=0, jPoint=0; iPart<pPolygon->Get_Part_Count(); iPart++)
361 		{
362 			nPoints[iPart]	= pPolygon->Get_Point_Count(iPart);
363 
364 			for(int iPoint=0; iPoint<pPolygon->Get_Point_Count(iPart); iPoint++, jPoint++)
365 			{
366 				Points[jPoint].x = (int)xWorld2DC(pPolygon->Get_Point(iPoint, iPart).x);
367 				Points[jPoint].y = (int)yWorld2DC(pPolygon->Get_Point(iPoint, iPart).y);
368 			}
369 		}
370 
371 		dc.DrawPolyPolygon(pPolygon->Get_Part_Count(), nPoints, Points, 0, 0, wxODDEVEN_RULE);
372 
373 		delete[]( Points);
374 		delete[](nPoints);
375 	}
376 }
377 
378 
379 ///////////////////////////////////////////////////////////
380 //														 //
381 //														 //
382 //														 //
383 ///////////////////////////////////////////////////////////
384 
385 //---------------------------------------------------------
386