Как определить, находится ли точка в пределах kml или формы

У меня есть некоторые данные формы (ряд файлов kml в столбце сводной таблицы и/или базы данных), и я хочу объединить их с другой таблицей, содержащей точки широты и долготы. По сути, мне нужен какой-то способ определить, содержится ли данная точка широты и долготы в одной из форм kml, и если да, то сохранить ссылку на эту строку. Я думал, что, возможно, есть способ сделать это из таблиц слияния, но если нет, возможно, есть способ перебрать каждый kml и проверить, содержится ли в нем точка lat lon. Я понимаю, что это не очень эффективно. Любая помощь, алгоритм, сервис и т. д. были бы замечательными.


person user379468    schedule 09.04.2012    source источник


Ответы (2)


API Fusion Tables SQL имеет оператор ST_INTERSECTS, но находит точки только внутри CIRCLE или RECTANGLE. GMap V3 имеет библиотеку геометрии, в которой есть метод poly.containsLocation(), который, я думаю, будет работать для произвольных полигонов. См.: геометрия/полибиблиотека GoogleMap.

P.S. Я понимаю, что это не работает для файлов KML, но они содержат точки полигонов, которые можно превратить в полигоны GMAP.

person Eric Bridger    schedule 09.04.2012
comment
Великолепно, это отличное начало - person user379468; 13.04.2012

Вероятно, это давно решено, но, поскольку у меня была аналогичная проблема, я решил опубликовать свое решение.

У меня было две таблицы Fusion: i) адрес и данные и ii) полигоны и данные. Я хотел иметь возможность легко запрашивать все адреса в пределах одного или нескольких полигонов. Я мог бы сделать это в реальном времени через свою веб-страницу картографирования, но решил, что лучше один раз заранее найти соответствующий полигон, а затем использовать эти данные для выполнения моих запросов картографирования (быстрее и проще указать несколько полигонов в веб-интерфейсе).

Итак, я экспортировал свою таблицу i) с адресами в листы Google и создал короткий простой скрипт, который проверял, в каком полигоне находится адрес, и записывал его обратно в лист Google. Затем я обновил свою таблицу слияния i).

У меня был набор данных почти из 3000 адресов и 2000 полигонов, так что время ожидания несколько раз истекло, и было несколько адресных ошибок, но это было легко исправить, и я просто настроил скрипт на запуск с первой строки, которая не был обновлен. Обратите внимание, что это не сработает, если полигоны накладываются друг на друга, но у меня этого не произошло, поскольку они были географическими границами ;-)

Код, который я использовал, приведен ниже, а также в здесь. Очевидно, вам нужно обновить идентификатор таблицы и, вероятно, нужно что-то сделать с OAuth (что я не совсем понял, но следовал инструкциям Google и сделал это).

// replace with your fusion table's id (from File > About this table)
var TABLE_ID = 'xxxxxxxxxx';

// first row that has data, as opposed to header information
var FIRST_DATA_ROW = 2;
var FIRST_DATA_COLUMN = 11;
var LAT_COLUMN = 1;
var LNG_COLUMN = 2;
var SA2_COLUMN = 6;
var SA3_COLUMN = 7;

/**
 * Uses a lat and lng data in google sheets to check if an address is within a kml polygon 
 * in a list of KML polygons in fusion (in this case ABS/ASGC SA2 and SA3 regions, but could be any polygon) 
 * the function then stores the ID/name of the relevant polygon in google sheets 
 * I could check this data in realtime as I render maps, but as it doesn't changed, figure its better to just record
 * which polygon each address pertains to so its quicker and easier to search (in particular it mades it easier to write a query
 * which identifies all the address within multiple polygons)
 * in this case I had 3000 rows so it exceeded maximum execution times, so I just updated the first data row a couple of times
 * when the execution time exceeded.
 */
function updateSA2ID() {
  var tasks = FusionTables.Task.list(TABLE_ID);  
  var sqlResponse = '';
  
  // Only run if there are no outstanding deletions or schema changes.
  if (tasks.totalItems === 0) {
    var sheet = SpreadsheetApp.getActiveSheet();
    var latLngData = sheet.getRange(FIRST_DATA_ROW, FIRST_DATA_COLUMN, sheet.getLastRow(), sheet.getLastColumn());
    
      i = 1;
    // Loop through the current current sheet
    for (i = 1; i <= latLngData.getNumRows(); i++) {      
      
      // cross reference to Fusion table
      lat = latLngData.getCell(i,LAT_COLUMN).getValue();
      lng = latLngData.getCell(i,LNG_COLUMN).getValue();
            
      sqlString = "SELECT 'SA2 Code', 'SA3 Code'  FROM " + TABLE_ID + " WHERE ST_INTERSECTS(geometry, CIRCLE(LATLNG(" + lat + ", " + lng + "),1)) ";      
      //Browser.msgBox('Lat ' + lat + ' Lng ' + lng + '; ' + sqlString, Browser.Buttons.OK);
      sqlResponse = FusionTables.Query.sql(sqlString);
      //Browser.msgBox('SQL Response ' + sqlResponse, Browser.Buttons.OK);

      latLngData.getCell(i,SA2_COLUMN).setValue(sqlResponse.rows[0][0]); // set SA2
      latLngData.getCell(i,SA3_COLUMN).setValue(sqlResponse.rows[0][1]); // set SA3     

    }
      
  } 
  else {
    Logger.log('Skipping row replacement because of ' + tasks.totalItems + ' active background task(s)');
  }
};

person PJB    schedule 27.09.2016