Подготовили небольшой пример для демонстрации выделения объектов по слоям на стандартной карте Ногинск из состава инсталляции: https://public.gisinfo.ru/Forum/test_example.zip Дополнительно приводим код примера:
Добавил добавление пользовательской карты и символа "Танк (общее обозначение)" из классификатора operator.rsc, цвет подсвечивания изменил на RGB(0, 255, 255). И ошибка воспроизвелась - на устройстве танк не подсветился:
Переданный пример (когда в функцию mapPaintAndSelectToXImage передается HSELECT) предназначен для отрисовки выделенных объектов на одной (базовой) карте. В случае, если открыто несколько карт, на одной из которых будут выделены объекты, необходимо выполнить следующее: - добавить установку контекста поиска в соответствующую карту с помощью функции mapSetSiteSeekSelect (sitapi.h); - установить поиск/выделение объектов только на этой карте с помощью функции mapSetTotalSeekMapRule (seekapi.h).
Ниже приводим обновленный пример, на основе описанных выше изменений (дополнительно упростили код примера). Пожалуйста, протестируйте и сообщите нам о результатах.
Код
#include <QApplication>
#include <QImage>
#include <ma th.h>
#include "qdmcmp.h"
#include "mapapi.h"
#include "maptype.h"
int main(int argc, char **argv)
{
QApplication application(argc, argv);
QDMapView();
HMAP mapHandle = mapOpenMapUn(WS("Noginsk/Noginsk.sit"));
CREATESITE createsite;
MAPREGISTER mapreg;
LISTREGISTER sheet;
memset(&createsite, 0, sizeof(CREATESITE));
memset(&mapreg, 0, sizeof(MAPREGISTER));
memset(&sheet, 0, sizeof(LISTREGISTER));
// Получим информацию о базовой карте
mapGetMapInfo(mapHandle, 1, &mapreg, &sheet);
// Имя пользовательской карты
strcpy(createsite.MapName, "Objects");
// Скопируем в создаваемую пользовательскую карту
createsite.Length = sizeof(createsite);
createsite.MapType = mapreg.MapType;
createsite.MaterialProjection = mapreg.MaterialProjection;
createsite.Scale = 100000;
createsite.FirstMainParallel = mapreg.FirstMainParallel;
createsite.SecondMainParallel = mapreg.SecondMainParallel;
createsite.AxisMeridian = mapreg.AxisMeridian;
createsite.MainPointParallel = mapreg.MainPointParallel;
char mapName[MAX_PATH_LONG];
char rscName[MAX_PATH_LONG];
// Разместить пользовательскую карту в том же каталоге рядом с базовой
SplitThePath(mapGetMainMapName(mapHandle), 0, mapName, 0, 0);
StrCopy(rscName, mapName, MAX_PATH_LONG);
StrCat(mapName, "objects.sit", MAX_PATH_LONG);
StrCat(rscName, "operator.rsc", MAX_PATH_LONG);
// Создать пользовательскую карту и добавить к базовой
HSITE hSite = mapCreateAndAppendSite(mapHandle, mapName, rscName, &createsite);
if (hSite == 0)
return 0;
double x1 = 6200000; // в метрах
double y1 = 7460000;
double x2 = 6190000;
double y2 = 7470000;
double midX = (x1+x2) / 2;
double midY = (y1+y2) / 2;
HOBJ hobj = mapCreateSiteObject(mapHandle, hSite);
mapRegisterObject(hobj, 112010010, LOCAL_VECTOR);
mapAppendPointPlane(hobj, midX, midY);
mapCommitObject(hobj);
HSELECT selectContext = mapCreateSiteSelectContext(mapHandle, hSite);
// Поиск объекта по порядковому номеру
mapSelectSampleByNumber(selectContext, 1, mapGetObjectNumber(hobj));
// Установить контекст поиска пользовательской карты
mapSetSiteSeekSelect(mapHandle, hSite, selectContext);
// Ограничить поиск объектов только для первой пользовательской карты
mapSetTotalSeekMapRule(mapHandle, 1);
mapSetTotalSelectFlag(mapHandle, 1);
// перевод в пиксели
mapPlaneToPicture(mapHandle, &x1, &y1);
mapPlaneToPicture(mapHandle, &x2, &y2);
int paintWidthInPixels = abs(x2 - x1);
int paintHeightInPixels = abs(y2 - y1);
RECT drawRectInPixels;
drawRectInPixels.left = x1;
drawRectInPixels.top = y1;
drawRectInPixels.right = x1 + paintWidthInPixels;
drawRectInPixels.bottom = y1 + paintHeightInPixels;
int paintDepthInBits = 32;
char *paintMemory = AllocateTheMemory(paintWidthInPixels * paintHeightInPixels * paintDepthInBits / 8);
if (paintMemory)
{
XIMAGEDESC xImageDesc;
xImageDesc.Point = paintMemory;
xImageDesc.Width = paintWidthInPixels;
xImageDesc.Height = paintHeightInPixels;
xImageDesc.Depth = paintDepthInBits;
xImageDesc.CellSize = xImageDesc.Depth / 8;
xImageDesc.RowSize = paintWidthInPixels * xImageDesc.CellSize;
if (mapPaintAndSelectToXImage(mapHandle, &xImageDesc, 0, 0, &drawRectInPixels, 0, RGB(0, 0, 255)));
{
QImage image((uchar *)paintMemory, paintWidthInPixels, paintHeightInPixels, QImage::Format_RGB32);
image.save("/tmp/out.png");
}
}
FreeTheMemory(paintMemory);
mapCloseData(mapHandle);
return 0;
}
Получается, что ошибка перестала воспроизводиться из-за удаления этих строк, а не из-за добавления строк
Код
// Установить контекст поиска пользовательской карты
mapSetSiteSeekSelect(mapHandle, hSite, selectContext2);
// Ограничить поиск объектов только для первой пользовательской карты
mapSetTotalSeekMapRule(mapHandle, 1);
Вернул удаленные вами строки, и ошибка стала вновь воспроизводиться. На всякий случай, получившийся код примера:
Код
#include <QApplication>
#include <QImage>
#include "qdmcmp.h"
#include "mapapi.h"
#include "maptype.h"
int main(int argc, char **argv)
{
QApplication application(argc, argv);
QDMapView();
//HMAP mapHandle = mapOpenMapUn(WTEXT("Noginsk/Noginsk.sit"));
#ifdef __arm__
QString myStr("/home/spo-dl/tmp/Noginsk/Noginsk.sit");
#else
QString myStr("/home/dmitry/experiments_panorama/highlight/from_panorama/Noginsk/Noginsk.sit");
#endif
std::u16string myU16Str = myStr.toStdU16String();
auto myU16Pc = myU16Str.c_str();
const WCHAR* myPWC = (const WCHAR*)myU16Pc;
HMAP mapHandle = mapOpenMapUn(myPWC);
CREATESITE createsite;
MAPREGISTER mapreg;
LISTREGISTER sheet;
memset(&createsite, 0, sizeof(CREATESITE));
memset(&mapreg, 0, sizeof(MAPREGISTER));
memset(&sheet, 0, sizeof(LISTREGISTER));
// Получим информацию о базовой карте
mapGetMapInfo(mapHandle, 1, &mapreg, &sheet);
// Имя пользовательской карты
strcpy(createsite.MapName, "Objects");
// Скопируем в создаваемую пользовательскую карту
createsite.Length = sizeof(createsite);
createsite.MapType = mapreg.MapType;
createsite.MaterialProjection = mapreg.MaterialProjection;
createsite.Scale = 100000;
createsite.FirstMainParallel = mapreg.FirstMainParallel;
createsite.SecondMainParallel = mapreg.SecondMainParallel;
createsite.AxisMeridian = mapreg.AxisMeridian;
createsite.MainPointParallel = mapreg.MainPointParallel;
char mapName[MAX_PATH_LONG];
char rscName[MAX_PATH_LONG];
// Разместить пользовательскую карту в том же каталоге рядом с базовой
SplitThePath(mapGetMainMapName(mapHandle), 0, mapName, 0, 0);
StrCopy(rscName, mapName, MAX_PATH_LONG);
StrCat(mapName, "objects.sit", MAX_PATH_LONG);
StrCat(rscName, "operator.rsc", MAX_PATH_LONG);
// Создать пользовательскую карту и добавить к базовой
HSITE hSite = mapCreateAndAppendSite(mapHandle, mapName, rscName, &createsite);
if (hSite == 0)
return 0;
// Создать контекст поиска с выделением объектов по слоям из классификатора (topo200t.print.rsc) для открытой карты Ногинск
HSELECT selectContext = mapCreateMapSelectContext(mapHandle);
mapSelectLayer(selectContext, -1, 0);
mapSelectLayer(selectContext, 8, 1); // Слой 8 - "Дорожная сеть"
mapSelectLayer(selectContext, 5, 1); // Слой 5 - "Гидрография"
double x1 = 6200000; // в метрах
double y1 = 7460000;
double x2 = 6190000;
double y2 = 7470000;
double midX = (x1+x2) / 2;
double midY = (y1+y2) / 2;
HOBJ hobj = mapCreateSiteObject(mapHandle, hSite);
mapRegisterObject(hobj, 112010010, LOCAL_VECTOR);
mapAppendPointPlane(hobj, midX, midY);
mapCommitObject(hobj);
HSELECT selectContext2 = mapCreateSiteSelectContext(mapHandle, hSite);
// Поиск объекта по порядковому номеру
mapSelectSampleByNumber(selectContext2, 1, mapGetObjectNumber(hobj));
// Установить контекст поиска пользовательской карты
mapSetSiteSeekSelect(mapHandle, hSite, selectContext2);
// Ограничить поиск объектов только для первой пользовательской карты
mapSetTotalSeekMapRule(mapHandle, 1);
// перевод в пиксели
mapPlaneToPicture(mapHandle, &x1, &y1);
mapPlaneToPicture(mapHandle, &x2, &y2);
int paintWidthInPixels = abs(x2 - x1);
int paintHeightInPixels = abs(y2 - y1);
RECT drawRectInPixels;
drawRectInPixels.left = x1;
drawRectInPixels.top = y1;
drawRectInPixels.right = x1 + paintWidthInPixels;
drawRectInPixels.bottom = y1 + paintHeightInPixels;
int paintDepthInBits = 32;
char *paintMemory = AllocateTheMemory(paintWidthInPixels * paintHeightInPixels * paintDepthInBits / 8);
if (paintMemory)
{
XIMAGEDESC xImageDesc;
xImageDesc.Point = paintMemory;
xImageDesc.Width = paintWidthInPixels;
xImageDesc.Height = paintHeightInPixels;
xImageDesc.Depth = paintDepthInBits;
xImageDesc.CellSize = xImageDesc.Depth / 8;
xImageDesc.RowSize = paintWidthInPixels * xImageDesc.CellSize;
mapSetViewSelect(mapHandle, selectContext);
if (mapPaintAndSelectToXImage(mapHandle, &xImageDesc, 0, 0, &drawRectInPixels, selectContext2, RGB(0, 255, 255)));
{
QImage image((uchar *)paintMemory, paintWidthInPixels, paintHeightInPixels, QImage::Format_RGB32);
image.save("/tmp/out.png");
}
}
FreeTheMemory(paintMemory);
mapCloseData(mapHandle);
return 0;
}
В этом варианте примера танк не подсвечивается. Если закомментировать строку
Код
mapSetViewSelect(mapHandle, selectContext);
то будет подсвечиваться. Хотелось бы добиться того, чтобы все работало корректно в варианте с возвращением удаленных вами строк.
В нашем проекте используются и другие контексты выделения - для скрытия объектов на пользовательской карте и для скрытия объектов основной карты. Будет ли все это адекватно работать, если применить ваш способ?
Должен ли работать предложенный вами способ с функцией mapDrawImageSelect? В нашем проекте используется функция mapDrawImageSelect, прямо перед ней написал предложенные вами строки, пятым аргументом установил 0. В результате перестали подсвечиваться объекты, которые до этого подсвечивались, а которые не подсвечивались - подсвечиваться не стали.
Дмитрий написал: Должен ли работать предложенный вами способ с функцией mapDrawImageSelect? В нашем проекте используется функция mapDrawImageSelect, прямо перед ней написал предложенные вами строки, пятым аргументом установил 0. В результате перестали подсвечиваться объекты, которые до этого подсвечивались, а которые не подсвечивались - подсвечиваться не стали.
Чтобы ответить на вопросы нужно видеть конкретный текст (фрагмент) программы.