5 #include "GVOWorldMap.h"
10 const double k_scaleStep = 0.125; // 12.5%
11 const double k_minScale = 0.125; // 12.5%
12 const double k_maxScale = 4.00; // 400%
16 bool GVOWorldMap::loadFromFile( const GVOConfig& config )
18 std::wstring filePath;
20 filePath = g_makeFullPath( config.m_mapFileName );
21 if ( !m_mapImage.loadFromFile( filePath.c_str() ) ) {
22 filePath = g_makeFullPath( config.m_defaultMapFileName );
23 if ( !m_mapImage.loadFromFile( filePath.c_str() ) ) {
28 //
\89æ
\91\9c\82Ì
\8d\82\82³
\82Æ
\88Ü
\93x
\82Ì
\94ä
\97¦
\82Ì
\83X
\83P
\81[
\83\8a\83\93\83O
\82Ì
\8aî
\8f\80\82Æ
\82È
\82é
\81B
29 const double mapHeight = m_mapImage.height();
30 m_ratioForImageCoordFromWorldCoord = mapHeight / k_worldHeight;
31 m_scaledMapSize = m_mapImage.size();
36 void GVOWorldMap::setViewSize( const SIZE& viewSize )
38 m_viewSize = viewSize;
39 m_viewCenter.x = m_viewSize.cx / 2;
40 m_viewCenter.y = m_viewSize.cy / 2;
44 void GVOWorldMap::offsetFocusInViewCoord( const POINT& offset )
46 const double dx = ((double)offset.x / m_viewScale) / m_mapImage.width();
47 const double dy = ((double)offset.y / m_viewScale) / m_mapImage.height();
49 LONG x = m_focusPointInWorldCoord.x + LONG( dx * k_worldWidth );
50 LONG y = m_focusPointInWorldCoord.y + LONG( dy * k_worldHeight );
51 y = max( 0, min( y, k_worldHeight ) );
55 while ( k_worldWidth < x ) {
59 m_focusPointInWorldCoord.x = x;
60 m_focusPointInWorldCoord.y = y;
64 void GVOWorldMap::setConfig( const GVOConfig& config )
66 m_positionUpdated = config.m_traceShipPositionEnabled;
67 m_focusPointInWorldCoord = config.m_initialSurveyCoord;
68 m_shipPointInWorld = config.m_initialSurveyCoord;
69 m_previousDrawPointInWorld = m_shipPointInWorld;
70 m_shipVectorLineEnabled = config.m_shipVectorLineEnabled;
74 void GVOWorldMap::setShipPosition( const POINT& worldCoord, bool isSyncCenter )
77 m_focusPointInWorldCoord = worldCoord;
79 if ( m_shipPointInWorld.x != worldCoord.x
80 || m_shipPointInWorld.y != worldCoord.y ) {
82 m_positionUpdated = true;
83 m_shipPointInWorld = worldCoord;
88 bool GVOWorldMap::zoomIn()
90 double scale = m_viewScale;
91 double step = k_scaleStep;
93 scale = m_viewScale + step;
94 if ( k_maxScale < scale ) {
97 if ( m_viewScale != scale ) {
106 bool GVOWorldMap::zoomOut()
108 double scale = m_viewScale;
109 double step = k_scaleStep;
111 scale = m_viewScale - step;
112 if ( scale < k_minScale ) {
115 if ( m_viewScale != scale ) {
124 void GVOWorldMap::drawMap( HDC hdc, const GVOShip& ship )
127 if ( m_viewScale < 1.0 ) {
129 ::GetBrushOrgEx( hdc, &brushOrg );
130 ::SetStretchBltMode( hdc, HALFTONE );
131 ::SetBrushOrgEx( hdc, brushOrg.x, brushOrg.y, NULL );
134 ::SetStretchBltMode( hdc, COLORONCOLOR );
137 HDC hdcMem = ::CreateCompatibleDC( hdc );
140 ::SelectObject( hdcMem, m_mapImage.bitmapHandle() );
142 const SIZE mapSize = m_scaledMapSize;
143 const POINT mapTopLeft = mapOriginInView();
145 int xDrawOrigin, yDrawOrigin;
146 xDrawOrigin = mapTopLeft.x;
147 yDrawOrigin = mapTopLeft.y;
149 if ( 0 < xDrawOrigin ) {
150 xDrawOrigin = (xDrawOrigin % mapSize.cx) - mapSize.cx;
152 const int xInitial = xDrawOrigin; //
\8d¶
\92[
\82Ì
\95`
\89æ
\8aJ
\8enx
\8dÀ
\95W
153 int drawn = xInitial; //
\95`
\89æ
\8dÏ
\82Ý
\8dÀ
\95W
155 //
\90¢
\8aE
\92n
\90}
\82ð
\89¡
\82É
\95À
\82×
\82Ä
\95`
\89æ
156 //
\81i
\95`
\89æ
\8dÅ
\93K
\89»
\82Í
\8fÈ
\97ª
\81j
157 while ( drawn < m_viewSize.cx ) {
159 xDrawOrigin, yDrawOrigin,
160 mapSize.cx, mapSize.cy,
163 m_mapImage.width(), m_mapImage.height(),
166 xDrawOrigin += mapSize.cx;
171 const POINT shipPointOffset = drawOffsetFromWorldCoord( m_shipPointInWorld );
173 //
\90j
\98H
\97\
\91ª
\90ü
\82ð
\95`
\89æ
174 if ( ship.isVectorEnabled() && m_shipVectorLineEnabled ) {
175 const int penWidth = max( 1, int(1 * m_viewScale) );
176 HPEN courseLinePen = ::CreatePen( PS_SOLID, penWidth, RGB( 255, 0, 255 ) );
177 HGDIOBJ oldPen = ::SelectObject( hdc, courseLinePen );
179 const LONG k_lineLength = k_worldHeight;
180 const POINT reachPointOffset = drawOffsetFromWorldCoord(
181 ship.pointFromOriginWithLength( m_shipPointInWorld, k_lineLength )
184 //
\8c©
\82¦
\82Ä
\82é
\92n
\90}
\89æ
\91\9c\82Ì
\95ª
\82¾
\82¯
\95`
\89æ
\82·
\82é
186 xDrawOrigin = xInitial;
187 while ( drawn < m_viewSize.cx ) {
188 const POINT shipPointInView = {
189 xDrawOrigin + shipPointOffset.x,
190 yDrawOrigin + shipPointOffset.y
192 const POINT reachPointInView = {
193 xDrawOrigin + reachPointOffset.x,
194 yDrawOrigin + reachPointOffset.y
196 ::MoveToEx( hdc, shipPointInView.x, shipPointInView.y, NULL );
197 ::LineTo( hdc, reachPointInView.x, reachPointInView.y );
198 xDrawOrigin += mapSize.cx;
202 ::SelectObject( hdc, oldPen );
203 ::DeleteObject( courseLinePen );
206 //
\8e©
\91D
\82Ì
\88Ê
\92u
\82ð
\95`
\89æ
207 const SIZE shipMarkSize = { 6, 6 };
208 HBRUSH shipBrush = ::CreateSolidBrush( RGB( 51, 238, 153 ) );
209 HGDIOBJ prevBrush = ::SelectObject( hdc, shipBrush );
211 //
\8c©
\82¦
\82Ä
\82é
\92n
\90}
\89æ
\91\9c\82Ì
\95ª
\82¾
\82¯
\95`
\89æ
\82·
\82é
213 xDrawOrigin = xInitial;
214 while ( drawn < m_viewSize.cx ) {
216 xDrawOrigin + shipPointOffset.x - shipMarkSize.cx / 2,
217 yDrawOrigin + shipPointOffset.y - shipMarkSize.cy / 2,
218 xDrawOrigin + shipPointOffset.x + shipMarkSize.cx,
219 yDrawOrigin + shipPointOffset.y + shipMarkSize.cy );
221 xDrawOrigin += mapSize.cx;
224 ::SelectObject( hdc, prevBrush );
225 ::DeleteObject( shipBrush );
228 ::RestoreDC( hdcMem, -1 );
229 ::DeleteDC( hdcMem );
230 ::RestoreDC( hdc, -1 );
234 void GVOWorldMap::updateShipRouteMap( HDC hdc )
236 //
\88Ú
\93®
\82µ
\82Ä
\82¢
\82È
\82¯
\82ê
\82Î
\89½
\82à
\82µ
\82È
\82¢
237 if ( !m_positionUpdated ) {
240 //
\88Ú
\93®
\82µ
\82Ä
\82¢
\82Ä
\82à
\8dq
\98H
\82ð
\8cq
\82°
\82È
\82¢
\82È
\82ç
\95`
\89æ
\82µ
\82È
\82¢
241 if ( !m_linkRoute ) {
242 m_previousDrawPointInWorld = m_shipPointInWorld;
247 const POINT& latestPoint = imageCoordFromWorldCoord( m_shipPointInWorld );
248 const POINT& previousPoint = imageCoordFromWorldCoord( m_previousDrawPointInWorld );
250 //
\95`
\89æ
\8dÀ
\95W
\82ª
\88ê
\8f\8f\82È
\82ç
\89½
\82à
\82µ
\82È
\82¢
251 if ( latestPoint.x == previousPoint.x
252 && latestPoint.y == previousPoint.y ) {
257 //
\8dÅ
\90V
\8dÀ
\95W
\82©
\82ç
\88ê
\82Â
\91O
\82Ì
\8dÀ
\95W
\82Ö
\90ü
\82ð
\88ø
\82
258 //
\90¢
\8aE
\82ð
\8c×
\82®
\8fê
\8d\87\82É
\8dl
\97¶
\82ª
\95K
\97v
\81B
259 //
\88Ú
\93®
\97Ê
\82ª
\88ê
\92è
\82ð
\92´
\82¦
\82½
\82ç
\95`
\89æ
\8f\88\97\9d\82µ
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\82Ì
\82ª
\83X
\83}
\81[
\83g
\82©
\82È
262 //
\90¢
\8aE
\82ð
\8c×
\82¢
\82¾
\82Æ
\82Ý
\82È
\82·è
\87\92l
263 const int k_distanceThreshold = m_mapImage.width() / 2;
265 const LONG xMin = min( latestPoint.x, previousPoint.x );
266 const LONG xMax = max( latestPoint.x, previousPoint.x );
267 const int xDistance = xMax - xMin;
270 HDC hdcMem = ::CreateCompatibleDC( hdc );
273 HPEN hpen = ::CreatePen( PS_SOLID, 1, RGB( 255, 255, 255 ) );
275 ::SelectObject( hdcMem, m_mapImage.bitmapHandle() );
276 ::SelectObject( hdcMem, hpen );
278 if ( k_distanceThreshold < xDistance ) {
279 if ( previousPoint.x < latestPoint.x ) { //
\90¢
\8aE
\82ð
\90¼
\82É
\8cü
\82©
\82Á
\82Ä
\8c×
\82¢
\82¾
280 //
\8d¶
\82Ì
\89æ
\96Ê
\8aO
\82©
\82ç
\8cü
\82©
\82¤
\90ü
\82ð
\95`
\89æ
281 LONG x3 = latestPoint.x - m_mapImage.width();
283 ::MoveToEx( hdcMem, x3, latestPoint.y, NULL );
284 ::LineTo( hdcMem, previousPoint.x, previousPoint.y );
286 //
\89E
\82Ì
\89æ
\96Ê
\8aO
\82É
\8cü
\82©
\82¤
\90ü
\82ð
\95`
\89æ
287 LONG x4 = previousPoint.x + m_mapImage.width();
288 ::MoveToEx( hdcMem, latestPoint.x, latestPoint.y, NULL );
289 ::LineTo( hdcMem, x4, previousPoint.y );
291 else { //
\90¢
\8aE
\82ð
\93\8c\82É
\8cü
\82©
\82Á
\82Ä
\8c×
\82¢
\82¾
292 //
\8d¶
\82Ì
\89æ
\96Ê
\8aO
\82©
\82ç
\8cü
\82©
\82¤
\90ü
\82ð
\95`
\89æ
293 LONG x3 = previousPoint.x - m_mapImage.width();
295 ::MoveToEx( hdcMem, latestPoint.x, latestPoint.y, NULL );
296 ::LineTo( hdcMem, x3, previousPoint.y );
298 //
\89E
\82Ì
\89æ
\96Ê
\8aO
\82É
\8cü
\82©
\82¤
\90ü
\82ð
\95`
\89æ
299 LONG x4 = latestPoint.x + m_mapImage.width();
300 ::MoveToEx( hdcMem, x4, latestPoint.y, NULL );
301 ::LineTo( hdcMem, previousPoint.x, previousPoint.y );
305 //
\8c×
\82ª
\82È
\82¢
\95`
\89æ
306 ::MoveToEx( hdcMem, latestPoint.x, latestPoint.y, NULL );
307 ::LineTo( hdcMem, previousPoint.x, previousPoint.y );
311 ::RestoreDC( hdcMem, -1 );
312 ::DeleteDC( hdcMem );
313 ::DeleteObject( hpen );
315 m_previousDrawPointInWorld = m_shipPointInWorld;
319 void GVOWorldMap::clearShipRoute()
321 const std::wstring fileName = m_mapImage.fileName();
322 m_mapImage.loadFromFile( fileName );
326 void GVOWorldMap::updateScaleCache()
328 m_scaledMapSize.cx = LONG( m_mapImage.width() * m_viewScale );
329 m_scaledMapSize.cy = LONG( m_mapImage.height() * m_viewScale );
333 POINT GVOWorldMap::mapOriginInView()
335 const POINT viewCenter = m_viewCenter;
336 const SIZE mapSize = m_scaledMapSize;
337 const POINT worldPosInView = drawOffsetFromWorldCoord( m_focusPointInWorldCoord );
340 viewCenter.x - worldPosInView.x,
341 viewCenter.y - worldPosInView.y
343 if ( m_viewSize.cx < mapSize.cx ) {
344 while ( 0 < mapTopLeft.x ) {
345 mapTopLeft.x -= mapSize.cx;
353 POINT GVOWorldMap::imageCoordFromWorldCoord( const POINT& worldCoord ) const
355 const double xNormPos = worldCoord.x / (double)k_worldWidth;
356 const double yNormPos = worldCoord.y / (double)k_worldHeight;
357 const POINT worldPosInImage = {
358 LONG( m_mapImage.width() * xNormPos ),
359 LONG( m_mapImage.height() * yNormPos )
361 return worldPosInImage;
364 POINT GVOWorldMap::drawOffsetFromWorldCoord( const POINT&worldCoord ) const
366 const POINT worldPosInImage = imageCoordFromWorldCoord( worldCoord );
367 const POINT drawOffset = {
368 LONG( worldPosInImage.x * m_viewScale ),
369 LONG( worldPosInImage.y * m_viewScale )