Здравствуйте, имеется следующая задача - создать новый объект по контуру другого (родительского объекта) с заданным отступом. Наглядно: http://prntscr.com/8e10cj , где черным - начальный объект, а красным - искомый. Затем у полученной копии изменить описание/имя на другое. В моём случае внутри объекта "болото" нужно создать объект "участок болота" (имеет штриховку), чтобы вышло так: http://prntscr.com/8e12my - справа то, что должно получиться. Сделал следующим образом, но оно не работает:
Код
HOBJ copy_info = mapCreateCopyObject(hMap, info);
long int result = mapInsideZoneObjectEx(-3, copy_info, 0, 0, 0.001, 3.);
mapDescribeObject(copy_info, 79758000);
mapCommitObjectAsNew(copy_info);
, где 79758000 - код объекта "участок болот" в классификаторе. Спасибо
Здравствуйте! Что конкретно не работает? copy_info точно содержит метрику до выполнения построения зоны? Чему у Вас равен result после выполнения функции? Что возвращает mapDescribeObject?
Попробуйте построить зону с параметрами: form = 1 - закругленный arcdist = 0.2 - расстояние между точками по дуге (в метрах на местности) рекомендуется radius / 15
Роман, данная функция не работает при следующих входных условиях: 1. петли в объекте (повторяющаяся метрика поверх существующей) 2. повторяющиеся точки в метрике 3. пересекающиеся сегменты ----- Автору перед тем как строить буфер(зону) вокруг объекта, очистите всю некорректную метрику функциями mapDeleteLoop и подобными. Более подробно в MapApi
Не тот глуп кто не знает, а тот, кто не знает где искать.
Роман Твердов пишет: Здравствуйте! Что конкретно не работает?
Цитата
KFF пишет: перед тем как строить буфер(зону) вокруг объекта, очистите всю некорректную метрику функциями mapDeleteLoop и подобными.
Да, что-то я действительно ничего не описал. Код сейчас имеет следующий вид:
Код
HOBJ copy_info = mapCreateCopyObject(hMap, info);
long int result_count = mapPointCount(copy_info, 0);
mapDeleteLoop(copy_info, (double)1e-3);
mapDeleteEqualPoint(copy_info, (double)1e-3, 0);
long int result_zone = mapInsideZoneObjectEx(-3, copy_info, 0, 1, 0.001 * mapGetMapScale(hMap), 3.);
long int result_describe = mapDescribeObject(copy_info, 79758000);
long int result_commit = mapCommitObjectAsNew(copy_info);
mapFreeObject(copy_info);
По коду, mapDeleteLoop, mapDeleteEqualPoint и mapInsideZoneObjectEx возвращают единицу. В result_describe оказывается 79758000. В result_commit передаётся общее число объектов на карте. ---------------------- Как оказалось, новый объект оно создаёт, даже верный контур. А не увидел я его потому, что результирующий объект получается линейным и совсем далёким от задаваемого значения. В mapDescribeObject я отправляю код 79758000, что соответствует площадному объекту "участок болот" в классификаторе. Написанный же выше код создаёт линейный объект "значок породы древостоя" с кодом 79719300 в классификаторе. Почему так выходит - это новый вопрос этой темы, первый можно считать устаревшим. Появился ещё второй вопрос - начальный объект, по метрике которого мы строим новый содержит порядка ста подобъектов, в то время как полученный их исключает. Как сделать так, чтобы вокруг подобъектов контур тоже строился? PS - и еще один, а то забыл. Начальный объект касается границы карты и поэтому отступ искомого объекта происходит в том числе и от границы карты. Можно ли этого избежать? Наглядно: http://prntscr.com/8emp61
Как сделать так, чтобы вокруг подобъектов контур тоже строился?
Перебором для всех подобъектов меняя subject
Код
Начальный объект касается границы карты и поэтому отступ искомого объекта происходит в том числе и от границы карты. Можно ли этого избежать?
У Вас же по рамке идет контур площадного объекта, для которого Вы строите зону. Готового решения для такой задачи нет. Можете попробовать перед Commit анализировать метрику объекта и при необходимости "притягивать" ее к рамке.
Извиняюсь за мою непонятливость. Это единственное, что осталось в моём вопросе, в остальном разобрался. Итак, код:
Код
//работа с полученным объектом info
HOBJ copy_info = mapCreateCopyObject(hMap, info);
//удаление циклов и совпадающих точек для проведения контура
mapDeleteLoop(copy_info, (double)1e-3);
mapDeleteEqualPoint(copy_info, (double)1e-3, 0);
//получение числа подобъектов + 1
//long int sub_count = mapPolyCount(copy_info);
for(long int i=1; i<sub_count; i++){
построение внутреннего контура
long int zone = mapInsideZoneObjectEx(-20, copy_info, i, 1, 0.001 * mapGetMapScale(hMap), 3.);
}
//изменение типа объекта на участки болот
mapRegisterObject(copy_info, 79758000, 1);
//сохранение нового объекта
mapCommitObjectAsNew(copy_info);
mapFreeObject(info);
mapFreeObject(copy_info);
Я не совсем понял какой идентификатор засылать в subject. Если делать как в коде, то новый объект не создаётся. Цикл начинал как с 0, так и с 1. На итерации i=0 и i=1 в zone записывается 1, значит ошибок нет. При i>1 результат zone = 0 у всех подобъектов, а их порядка 90шт. Если заслать без цикла subject = -1, то подобъекты начинают учитываться, но пропадает отступ, а, соответственно, и весь смысл операции. Где в моём коде ошибка, что я сделал не так?
1. Построить зону для объекта (subject = 0) со значением -20. Записать ее в объект с кодом 79758000. 2. Далее для каждого подобъекта в цикле (subject=1..sub_count) построить его зону со значением +20. Полученную метрику записать как подобъект в объект полученный в результате шага 1.
Вам нужно всегда иметь метрику исходного объекта, т.к. mapInsideZoneObjectEx записывает метрику построенной зоны в передаваемый hobj.
Роман Твердов пишет: Полученную метрику записать как подобъект в объект полученный в результате шага 1.
Я очень извиняюсь за дотошность, я сейчас около получаса втыкал в API, форум и руководство, но не нашёл как правильно добавлять подобъект к объекту. Готовой функции в API я не увидел, есть только догадка насчёт добавления дескриптора в метрику главного объекта
Код
// Создать дескриптор подобъекта в записи метрики
// В конец записи добавляется дескриптор подобъекта
// Выполняется контроль по длине записи и длине буфера
// Число точек = 0, номер подобъекта = максимальный номер + 1
// (как правило, записывается порядковый номер подобъекта)
// info - идентификатор объекта карты в памяти
// При ошибке возвращает ноль
_MAPIMP long int _MAPAPI mapCreateSubject(HOBJ info);
, а затем добавлять каждую точку метрики в конец основного объекта с помощью: mapInsertPointGeo(); Собственно, я так и сделал, нужный мне результат получил.
Во время написания возникла некоторая проблема. На форуме я нашёл следующее сообщение: http://www.gisweb.ru/forum/messages/forum2/topic3428/message21872/#message21872 В сообщении пример создания подобъекта и в этом примере при добавлении точек после mapCreateSubject() четвёртый аргумент (номер подобъекта) в mapAppendPointPlane() не засылался. Когда я сделал аналогично, у меня вся метрика подобъектов записалась в объект, все подобъекты были созданы, но их метрика была пустой. Пришлось добавлять четвёртый аргумент и тогда всё заработало:
Код
//получение числа подобъектов + 1
long int sub_count = mapPolyCount(info);
//цикл добавления подобъектов
for(long int i=1; i<sub_count; i++){
//копирование начального объекта в temp для получения очередного подобъекта
HOBJ temp_info = mapCreateCopyObject(hMap, info);
//построение внешнего контура для подобъекта i
long int result_zone = mapInsideZoneObjectEx(step, temp_info, i, 1,
0.001 * mapGetMapScale(hMap), 3.);
//если зона построена успешно
if (result_zone>0){
//создаём новый подобъект для искомого объекта
mapCreateSubject(new_info);
//все точки темпового объекта переносим в подобъект
long int point_count = mapPointCount(temp_info, 0);
long int new_sub_count = mapPolyCount(new_info);
for(long int i=1; i<point_count; i++){
double point_x = mapXPlane(temp_info, i, 0);
double point_y = mapYPlane(temp_info, i, 0);
mapAppendPointPlane(new_info, point_x, point_y, new_sub_count-1);
}
}
mapFreeObject(temp_info);
}
На основании этого и вопрос, это я чего упустил или пример в том сообщении был неверный? Спасибо за помощь.