📄 viewmap.cpp
字号:
FitText(pDC, pMapLayerObj, pMapLayer, x, y);
};
};
}
DrawText(pDC, pMapLayer);
};
}
/////////////////////////////////////////////////////////////////////////////
void CViewMap::GetExtent(CMapLayer* pMapLayer, CMapLayerObj* pMapLayerObj)
{
CRectEx rectE, rectPMax;
CRect& rRect = pMapLayerObj->GetExtent();
// TODO need to optimise by determining centroid automatically as extent is loaded
// from shapefiles for overlays and could be stored in CLongBinary
if ((rRect.left == 0 && rRect.right == 0) ||
(pMapLayerObj->GetCentreX() == 0 && pMapLayerObj->GetCentreY() == 0))
{
if (pMapLayerObj->GetDataType() == BDMAPLINES)
{
CLongLines* pMapLines = (CLongLines*)pMapLayerObj->GetMapObject();
// Determine extent of maplines
// Determine extent of largest polygon/polyline so as to
// exclude islands etc.
CRectEx rectP;
for (int i = 0; i < pMapLines->GetSize(); i++)
{
CLongCoord coord = pMapLines->GetAt(i);
if (!coord.IsNull())
{
// Determine the extent of the polyline
if (rectP.IsEmpty())
{
rectP.left = rectP.right = coord.x;
rectP.top = rectP.bottom = coord.y;
} else
{
rectP.left = min(rectP.left, coord.x);
rectP.right = max(rectP.right, coord.x);
rectP.top = min(rectP.top, coord.y);
rectP.bottom = max(rectP.bottom, coord.y);
}
}
if (coord.IsNull() || i+1 == pMapLines->GetSize())
{
// Determine the overall extent
if (rectE.IsEmpty())
{
rectE = rectP;
} else if (!rectP.IsEmpty())
{
rectE.left = min(rectE.left, rectP.left);
rectE.right = max(rectE.right, rectP.right);
rectE.top = min(rectE.top, rectP.top);
rectE.bottom = max(rectE.bottom, rectP.bottom);
};
// Determine the extent of the largest polgon
if (fabs(rectPMax.Area()) < fabs(rectP.Area()))
{
rectPMax = rectP;
}
rectP = CRectEx();
}
};
}
else if (pMapLayerObj->GetDataType() == BDCOORD)
{
CCoord* pCoord = (CCoord*)pMapLayerObj->GetMapObject();
double dX = GetfXInv((int)pMapLayer->GetSymSize()) - GetfXInv(0);
rectE.left = (int)(pCoord->x - dX*2 + 0.5);
rectE.right = (int)(pCoord->x + dX*2 + 0.5);
rectE.top = (int)(pCoord->y - dX*2 + 0.5);
rectE.bottom = (int)(pCoord->y + dX*2 + 0.5);
rectPMax = rectE;
}
// Determine extent for images
else if (pMapLayerObj->GetDataType() == BDIMAGE)
{
double dX, dY;
CImageFile* pImageFile = (CImageFile*)pMapLayerObj->GetMapObject();
pImageFile->m_georef.Convert(CPoint(0,0), dX, dY);
rectE.left = (int)dX;
rectE.bottom = (int)dY;
pImageFile->m_georef.Convert(CPoint(pImageFile->m_buffer.width-1, pImageFile->m_buffer.height-1), dX, dY);
rectE.right = (int)dX;
rectE.top = (int)dY;
rectPMax = rectE;
}
// Store the result
if (!rectE.IsEmpty())
{
rRect = rectE;
// Store the centre of the largest polygon
pMapLayerObj->GetCentreX() = (rectPMax.right + rectPMax.left)/2;
pMapLayerObj->GetCentreY() = (rectPMax.bottom + rectPMax.top)/2;
}
};
}
/////////////////////////////////////////////////////////////////////////////
//
// Determine if the map layer is visible within the current map extent. If
// not, offer to update the extent
//
void CViewMap::CheckExtent(CMapLayerArray* pMapLayerArray)
{
CBDProjection projection;
// Determine the full extent of the view
CRect rectNew = CRect(0,0,0,0);
CRect rectAll = CRect(0,0,0,0);
for (int j = 0; j < pMapLayerArray->GetSize(); j++)
{
CMapLayer* pMapLayer = pMapLayerArray->GetAt(j);
for (int i = 0; i < pMapLayer->GetSize(); i++)
{
CMapLayerObj* pMapObj = pMapLayer->GetAt(i);
// Determine extent of new layers
if (!pMapLayer->IsExtentChecked())
{
if (rectNew.IsRectNull())
{
rectNew = pMapObj->GetExtent();
} else
{
rectNew.top = min(rectNew.top, pMapObj->GetExtent().top);
rectNew.bottom = max(rectNew.bottom, pMapObj->GetExtent().bottom);
rectNew.left = min(rectNew.left, pMapObj->GetExtent().left);
rectNew.right = max(rectNew.right, pMapObj->GetExtent().right);
}
}
// Determine total extent
if (rectAll.IsRectNull())
{
rectAll = pMapObj->GetExtent();
} else
{
rectAll.top = min(rectAll.top, pMapObj->GetExtent().top);
rectAll.bottom = max(rectAll.bottom, pMapObj->GetExtent().bottom);
rectAll.left = min(rectAll.left, pMapObj->GetExtent().left);
rectAll.right = max(rectAll.right, pMapObj->GetExtent().right);
}
}
pMapLayer->SetExtentChecked();
};
// If the view does not fit in the default view then offer to update it
if (rectNew.left != rectNew.right)
{
if (m_bDefaultExtentNull ||
((rectNew.right < m_dMinX || rectNew.left > m_dMaxX) &&
(rectNew.top < m_dMinY || rectNew.bottom > m_dMaxY)))
{
// Ask the user if the view should be updated
if (AfxMessageBox(IDS_OUTSIDEEXTENT, MB_YESNO) == IDYES)
{
// Find the default projection
BOOL bFound = BDProjection(BDHandle(), &projection, BDGETINIT);
while (bFound)
{
// Update it
if (projection.m_bDefault)
{
BDEnd(BDHandle());
projection.m_dMinEasting = rectAll.left;
projection.m_dMaxEasting = rectAll.right;
projection.m_dMinNorthing = rectAll.top;
projection.m_dMaxNorthing = rectAll.bottom;
BDProjection(BDHandle(), &projection, BDUPDATE);
m_bDefaultExtentNull = FALSE;
// Initialise and redraw the view
InitialiseMapView();
OnViewZoomnormal();
break;
};
bFound = BDGetNext(BDHandle());
};
BDEnd(BDHandle());
// Initialise to latitude/longitude
if (!bFound)
{
InitialiseMapView();
OnViewZoomnormal();
}
};
};
};
}
/////////////////////////////////////////////////////////////////////////////
void CViewMap::DrawCoords(CDC* pDC, CMapLayerObj* pMapLayerObj, CMapLayer* pMapLayer, BOOL bSearch)
{
CBrush brush;
CRect rectWindow;
char* pName = NULL;
CRect rectI;
// Optimization: If the extent is outside the current view then no need to draw, should
// speed up drawing of custom symbols as well as prevent Win 98 from crashing when zoomed in
// Determine the extent
GetExtent(pMapLayer, pMapLayerObj);
if (!IsVisible(pDC, pMapLayerObj)) return;
CMapStyle mapstyle;
GetStyle(pMapLayer, pMapLayerObj, 0, mapstyle);
if (bSearch)
{
mapstyle.m_crFill = RGB(255,255,255);
mapstyle.m_crLine = RGB(255,0,0);
}
// Convert the coordinate to screen coordinates
CCoord* pCoord = (CCoord*)pMapLayerObj->GetMapObject();
if (pCoord != NULL && !pCoord->IsNull())
{
double dX = GetfXPos((long)(pCoord->x + 0.5));
double dY = GetfYPos((long)(pCoord->y + 0.5));
// Determine the auto symbol size
if (pMapLayer->GetAutoSize())
{
ASSERT(pMapLayer->GetAutoMax() - pMapLayer->GetAutoMin() != 0);
if (pMapLayerObj->GetValue() != AFX_RFX_DOUBLE_PSEUDO_NULL)
{
double d = (pMapLayerObj->GetValue() - pMapLayer->GetAutoMin()) /
(pMapLayer->GetAutoMax() - pMapLayer->GetAutoMin());
mapstyle.m_dSymSize *= AUTOSCALE*d;
}
}
// Scale the symbol
if (pMapLayer->GetScaleFont())
{
mapstyle.m_dSymSize *= m_dZoom;
}
// Draw position of station
if (pMapLayer->GetBestFitSym())
{
CheckOverlapSym(pDC, mapstyle.m_dSymSize, dX, dY);
}
CComboBoxSymbol::DrawSymbol(pDC, dX, dY, mapstyle);
};
}
///////////////////////////////////////////////////////////////////////////////
//
// Display a georeferenced image associated with a map object
//
void CViewMap::DrawImage(CDC* pDC, CMapLayerObj* pMapLayerObj, CMapLayer* pMapLayer)
{
CImageFile* pImage = (CImageFile*)pMapLayerObj->GetMapObject();
// Determine if window is visible
GetExtent(pMapLayer, pMapLayerObj);
if (!IsVisible(pDC, pMapLayerObj)) return;
// Determine location of window
CRect rect = m_rect;
if (m_rectPaint.left != 0 && m_rectPaint.right != 0)
{
rect.IntersectRect(m_rect, m_rectPaint);
};
pImage->OnDraw(pDC, this, &rect);
}
///////////////////////////////////////////////////////////////////////////////
void CViewMap::FitText(CDC* pDC, CMapLayerObj* pMapLayerObj, CMapLayer* pMapLayer,
int x, int y)
{
CRect rect;
BOOL bDrawText = FALSE;
CRectText rectT;
int iPos = 0;
// Search through all posible positions
bDrawText = CheckOverlap(pDC, pMapLayer, pMapLayerObj->GetText(), x, y, rect, iPos);
// If overlaps are allowed and the text cannot be fit
// then draw it anyway
if (pMapLayer->GetOverlap()) bDrawText = TRUE;
// If the text label is outside the drawn rectangle then do not draw it
if (rect.left < m_rect.left || rect.right > m_rect.right ||
rect.top < m_rect.top || rect.bottom > m_rect.bottom)
{
bDrawText = FALSE;
}
if (bDrawText)
{
rectT.m_sText = pMapLayerObj->GetText();
rectT.m_rect = rect;
rectT.m_iPos = iPos;
rectT.m_nX = x;
rectT.m_nY = y;
m_aRectTextL.Add(rectT);
};
}
///////////////////////////////////////////////////////////////////////////////
void CViewMap::DrawText(CDC* pDC, CMapLayer* pMapLayer)
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(pMapLayer->GetTextColour());
// Output the text
for (int i = 0; i < m_aRectTextL.GetSize(); i++)
{
pDC->TextOut(m_aRectTextL[i].m_rect.left, m_aRectTextL[i].m_rect.top,
m_aRectTextL[i].m_sText);
};
// Copy the text areas
for (i = 0; i < m_aRectTextL.GetSize(); i++)
{
m_aRectText.Add(m_aRectTextL[i].m_rect);
}
m_aRectTextL.RemoveAll();
}
///////////////////////////////////////////////////////////////////////////////
//
// Returns true if the coordinate can be drawn and the rectangle into which
// it will be drawn
//
BOOL CViewMap::CheckOverlap(CDC* pDC, CMapLayer* pMapLayer, LPCSTR sText,
int nX, int nY, CRect& rect, int& iPos)
{
CSize sz(0,0);
int nPosMin, nPosMax;
BOOL bDrawText = FALSE;
CRect rectI;
int iOverlap = -1;
if (pMapLayer->GetSize() == 0) return FALSE;
BOOL bMapLines = pMapLayer->GetAt(0)->GetDataType() == BDMAPLINES;
// Determine the range of available positions
if (pMapLayer->GetTextPos() == CMapLayer::BestFit)
{
if (!bMapLines)
{
nPosMin = CMapLayer::BottomRight;
nPosMax = CMapLayer::BottomLeft;
} else
{
nPosMin = CMapLayer::BottomRight;
nPosMax = CMapLayer::Center;
}
} else
{
nPosMin = pMapLayer->GetTextPos();
nPosMax = pMapLayer->GetTextPos();
}
// If refitting then start from last position
if (iPos != 0)
{
nPosMin = iPos;
};
// Determine the rectangle
sz = pDC->GetTextExtent(sText);
for (iPos = nPosMin; iPos <= nPosMax && !bDrawText; iPos++)
{
bDrawText = TRUE;
// For maplines, make centre the default option
int nPos = iPos;
if (pMapLayer->GetTextPos() == CMapLayer::BestFit && bMapLines)
{
nPos = CMapLayer::Center - iPos;
}
switch (nPos)
{
case CMapLayer::TopLeft :
rect.left = nX - sz.cx - 2;
rect.top = nY - sz.cy -2;
break;
case CMapLayer::BottomRight :
rect.left = nX +2;
rect.top = nY+2;
break;
case CMapLayer::TopRight :
rect.left = nX +2;
rect.top = nY - sz.cy -2;
break;
case CMapLayer::BottomLeft:
rect.left = nX - sz.cx - 2;
rect.top = nY+2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -