На скриншотах, взятых из моего приложения MFC, показаны линии 2, которые должны быть параллельными.
Линии нарисованы с использованием Gdiplus::Graphics::Drawline()
,
Незначительная проблема в том, что пунктирные линии не прямые, а ломаные. Вы замечаете это, но это не имеет большого значения …
Реальная проблема заключается в том, что это не соответствует и линии, нарисованные с Gdiplus::DashStyleSolid
действительно прямые.
Это ошибка в GDI +? Есть ли обходной путь?
Я попытался сделать минимальный пример, но я изо всех сил пытаюсь воспроизвести его …
Это может быть связано с очень большими значениями координат и небольшой разницей между их координатами.
Вот некоторые примерные координаты линии:
Line 1: PointF(2.21866e+006, 1.40198e+006), PointF(2.21732e+006, 1.40111e+006)
Line 2: PointF(2.21866e+006, 1.40198e+006), PointF(2.21732e+006, 1.40112e+006)
Я заметил, что начальные точки идентичны, но это может быть вызвано округлением в выводе отладки …
Я мог бы воспроизвести это сейчас:
Пример приложения был сгенерирован как проект SDI, а класс представления наследует CScrollView (код и снимок экрана ниже).
Эффект «пунктирной линии» также, по-видимому, связан с толщиной пера. Линия проходит немного по-разному с изменяющейся толщиной, но я не нашел значения, которое все время приводит к параллельным линиям.
Винсент Порвик предлагает в комментарии, что это может быть результатом ошибок округления, так как Gdiplus::REAL
определяется как float
,
Я тоже так считаю …
Есть ли у меня какие-либо варианты, кроме как использовать меньшие значения координат здесь?
Эти функции были добавлены / изменены (в дополнение к коду инициализации GDI +):
void CgdiplusLinesView::OnDraw(CDC* pDC)
{
CgdiplusLinesDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDC->SetBkMode(TRANSPARENT);
using namespace Gdiplus;
Graphics g(pDC->m_hDC);
g.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
Pen solidPen(Color(0,0,0), 2.f);
Pen dashedPen(Color(0,0,0), 2.f);
dashedPen.SetDashStyle(DashStyleDash);
g.DrawLine(&dashedPen, PointF(4438749.500000, 2805806.500000), PointF(4434280.500000, 2802106.500000));
g.DrawLine(&solidPen, PointF(4438746.500000, 2805809.500000), PointF(4434277.500000, 2802109.500000));
}
void CgdiplusLinesView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode(MM_ISOTROPIC);
const int mapSizePixels = 8388608;
pDC->SetWindowExt(mapSizePixels, mapSizePixels);
pDC->SetViewportExt(mapSizePixels, mapSizePixels);
pDC->SetWindowOrg(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
//__super::OnPrepareDC(pDC, pInfo);
}
void CgdiplusLinesView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
SetScrollSizes(MM_TEXT, CSize(8388608, 8388608), CSize(1361, 1054));
SetScrollPos(SB_HORZ, 4434897.5);
SetScrollPos(SB_VERT, 2802645.);
}
Я не думаю, что это связано с пунктирной и сплошной, но с точностью поплавка. Ваши координаты кажутся географическими. Обычно рекомендуется хранить все координаты как двойные, и когда вам нужно работать с библиотекой с меньшей точностью, сместите все координаты самостоятельно, прежде чем передавать их графическим функциям.
Правильный способ сделать это — выбрать опорную точку, близкую к точкам в вашем наборе данных (первая найденная вами координата в порядке), а затем вычесть ее координаты всем остальным точкам. Это сохраняет числовые значения около 0,0, то есть где поплавки имеют более высокую плотность разрешения.
Других решений пока нет …