Базы данных Oracle - статьи

full production support in Cyprus          

Визуализация новой карты


Код в секции "rendering a new map" (рендеринг новой карты) файла main.jsp формирует запрос к карте и посылает его к серверу MapViewer. Большая часть логики, имеющей отношение к карте, а также ваши собственные геопространственные запросы выполняются здесь через клиентский Java API.

Чтобы выполнить рендеринг новой карты, вы сначала берете две ссылки к экземплярам клиентов MapViewer из текущей пользовательской сессии. Как правило, только один такой клиент требуется, чтобы посылать запросы к карте и получать ответы. Наше приложение-пример, однако, использует поддержку нового HTML-изображения карты, так что вам нужен отдельный MapViewer-клиент, чтобы послать несколько другой запрос к карте.

Создание новых клиентов MapViewer. Для новой сессии браузера или вы не можете получить доступ к существующему экземпляру клиента MapViewer, если, например, время сессии истекло, вы создаете новые экземпляры этого клиента с применением кода листинга 1.

Код листинга 1: Создание экземпляров клиента

if (mv == null newSession) // new session { mv = new MapViewer(mvURL); // one for the main map request session.setAttribute("oramap", mv); // keep client handle in the session

mv.setDataSourceName(dataSrc); // specify the data source (database) mv.setImageFormat(MapViewer.FORMAT_PNG_URL); // PNG Image mv.setMapTitle(title); // set map title // specify marker symbol denoting map center mv.setDefaultStyleForCenter("M.IMAGE89_BW", null, null, null); mv.setAntiAliasing(true); //make map look nicer mv.setCenterAndSize(cx, cy, size); // initial center & size mv.setDeviceSize(new Dimension(width, height)); // window size // Specify themes to display. States, Cities, and field office locations mv.addPredefinedTheme("THEME_DEMO_STATES"); mv.addPredefinedTheme("THEME_DEMO_BIGCITIES"); mv.addPredefinedTheme("FIELD OFFICE");

// now create MapViewer instance for handling HTML image maps clkmv = new MapViewer(mvURL); // for "FIELD OFFICE CLK" theme. clkmv.setDataSourceName(dataSrc); // same data source clkmv.setCenterAndSize(cx, cy, size); // and center and size // but different image format. We use SVG to construct the image map clkmv.setSVGFragmentType(MapViewer.SVG_LAYERS_WITH_LABELS) ; clkmv.setSVGFragmentInDeviceCoord(true);


clkmv.setDeviceSize(new Dimension(width, height)); // specify the theme. FIELD OFFICE CLK lists the attributes // that show up in an info-tip clkmv.addPredefinedTheme("FIELD OFFICE CLK"); session.setAttribute("oramap_clk", clkmv);

// submit the two map requests mv.run(); clkmv.run(); }

Эти два экземпляра клиента MapViewer (иначе называемые handles или beans) -- mv и clkmv. Первый, mv, служит главным клиентом для конструирования и посылки регулярных запросов к карте, в то время как clkmv посылает запросы к HTML-изображениям карты.

Темы и стили: Как отображаются полевые офисы. Запросы к карте клиента mv включают три предопределенных темы. Ключевая тема – это FIELD OFFICE, которая определяется в USER_SDO_THEMES:

SQL> select base_table, geometry_column, styling_rules from user_sdo_themes where name='FIELD OFFICE';

Результат этого запроса:

FIELD_OFFICES LOCATION <?xml version="1.0" standalone="yes"?> <styling_rules> <rule column="HEADCOUNT" order_by="HEADCOUNT" sort_order="DESC"> <features style= "OFFICE_STYLE"> </features>

<label column="NAME" style="T.STREET NAME"> headcount - 250 </label> </rule> </styling_rules>

Так что FIELD_OFFICES – это базовая таблица для этой темы и столбец LOCATION содержит данные о расположении каждого офиса.

Определение STYLING_RULES специфицирует, что столбцы HEADCOUNT, NAME и LOCATION запрашиваются из FIELD_OFFICES. Оно также предусматривает, что результат сортируется в убывающем порядке значения HEADCOUNT. Это важно, так как вы показываете полевые офисы, как кружки переменных размеров, определяемых значениями HEADCOUNT. Если расположения двух офисов близки друг к другу, вы захотите, чтобы MapViewer выполнил рендеринг сначала большего кружка, а затем поверх него меньшего.

Некий объект обладает меткой только тогда, когда числовое значение столбца LABEL больше, чем 0. Элемент <label> выше имеет условие "headcount - 250," так что MapViewer присваивает метки, только если его head count больше чем 250.





Единственное назначение клиента clkmv – посылать запрос к карте, содержащий тему FIELD OFFICE CLK. Это весьма похоже на тему FIELD OFFICE, используемую клиентом mv, единственное отличие в том, что он сортирует офисы в возрастающем порядке перечисления, так что большие области HTML-изображения карты, сгенерированные для полевых офисов, появляются в списке областей после малых. Тема FIELD OFFICE CLK также имеет элемент <hidden_info>:

<styling_rules > <hidden_info> <field column="NAME" name="Office" /> <field column="HEADCOUNT" name="#Employee" /> <field column="ADDRESS" name="Address" />

<field column="CITY" name="City" /> <field column="STATE" name="State" /> </hidden_info> ... </rule>

MapViewer выбирает столбцы, запрошенные в элементе <hidden_info>, как часть запроса и включает их в ответ (результат) карты.

Клиент mv просит сервер выполнить рендеринг карты в PNG-файл, сохранить его на сервере-хосте и возвратить URL для файла-изображения, который будет представлен в браузере. Клиент clkmv, в свою очередь, использует файловый формат Scalable Vector Graphics (SVG):

clkmv.setSVGFragmentType( MapViewer.SVG_STYLED_LAYERS_WITH_LABELS) ; clkmv.setSVGFragmentInDeviceCoord(true);

Эти два метода “говорят” MapViewer о создании SVG-карты по запросу и возврате SVG-документа, содержащего данные карты в системе координат устройства. Эти координаты используются для генерации областей HTML-изображений карты.

Создав обоих клиентов, вы вызываете метод run(), который посылает запрос серверу. Клиенты ждут ответа и извлекают нужную информацию, такую как URL сгенерированного изображения карты, используя методы доступа.

Теперь, когда вы знаете, как специфицируются контент карты и формат, можно рассмотреть, как выполняется рендеринг расположений полевых офисов. Правила стиля для двух полевых офисов ссылаются на стиль OFFICE_STYLE, который можно назвать продвинутым, основанным на участах памяти (bucket-based). OFFICE_STYLE содержит набор участков (buckets), каждый из них соответствует диапазону значений, такому как 250 < headcount < 500, со примитив-стилем (primitive style), таким как красный кружок (red circle). Для тем FIELD OFFICE каждое значение упорядоченности (head count) определяет его участок и стиль.

Обработка действий пользователя (Processing user actions). Параметр action в файле main.jsp содержит информацию о взаимодействии с пользователем. Если значение параметра action - pan, zoomin, zoomout или zoombox, вы повторно выдаете запрос к карте, вызывая соответствующие методы, такие как pan(), с новыми параметрами центра и размеров. Вы всегда вызываете эти методы на обоих клиентах, так что карта с HTML-изображениями, сгенерированная в clkmv, синхронизирована с изображением показываемой карты.

Обработка ID-функции (Processing the ID function). Действие ID инициируется тогда, когда пользователь щелкает по кнопке ID на инструментальной панели и затем щелкает где-нибудь на карте. Фактически эта обработка происходит на стороне сервера.



Листинг 2 показывает соответствующий сегмент кода для обработки ID-действия.

Код листинга 2: Обработка ID-действия

else if("id".equals(action)) { String[] columns = new String[]{"NAME Nearest_Office", "City", "State", "a.location.sdo_point.x X", "a.location.sdo_point.y Y", "Headcount"};

//find out the office nearest to where user clicked on the map officeInfo = mv.identify(dataSrc, "field_offices a", //the table name columns, // columns in SELECT clause "location", // geometry column name srid, // spatial reference system id mapClickX, mapClickY //mouse click position ); Point2D officeLoc = null; if(officeInfo!=null) { // identify() returns a String[][] of row, column values // row 0 is the column name list, row 1 on are values // columns are named in the "columns" parameter // so here column 0 is Name, 1 is City, 2 is State, // 3 is X, and 4 is Y String x = officeInfo[1][3]; String y = officeInfo[1][4]; officeLoc = new Point2D.Double(Double.parseDouble(x), Double.parseDouble(y)); }

// mark user click on the map with a PIN marker Point2D p2 = mv.getUserPoint(mapClickX, mapClickY); mv.addPointFeature(p2.getX(), p2.getY(), srid, "M.CYAN PIN", //a PIN marker style null, null, null);

//add a leader line from user click to nearest office if(officeLoc!=null) mv.addLinearFeature(new double[]{p2.getX(), p2.getY(), officeLoc.getX(), officeLoc.getY()}, srid, "NEAREST_LINE_STY", null, null, false);

/* For identify: use previously generated map as backdrop and avoid rerendering all base themes. */ if(mv.getBackgroundImageURL()==null) mv.setBackgroundImageURL(mv.getGeneratedMapImageURL()); String[] enabledThemes = mv.getEnabledThemes(); mv.setAllThemesEnabled(false); //temporarily disable themes

mv.run(); // reissue map request to draw a PIN marker // reenable all themes mv.enableThemes(enabledThemes);

mv.removeAllPointFeatures(); // clean up PIN marker mv.removeAllLinearFeatures(); // clean up leader line as well } // end id action



Код в листинге 2 сначала находит полевой офис, ближайший к расположению, заданному пользователем, используя метод identify(). Входные параметры – это имя целевой таблицы (FIELD_OFFICES), по которой будет производиться поиск, список возвращаемых столбцов и расположение мыши в системе координат экрана.

Далее, код определяет координаты основания, соответствующие расположению этого клика мыши:

Point2D p2 = mv.getUserPoint( mapClickX, mapClickY);

Затем код добавляет символ маркера PIN к этому расположению:

mv.addPointFeature( p2.getX(), p2.getY(), srid, "M.CYAN PIN", //a PIN marker style null, null, null);

Далее, код добавляет линию, соединяющую эти два расположения с новой картой:

mv.addLinearFeature( new double[]{p2.getX(), p2.getY(), officeLoc.getX(), officeLoc.getY()}, srid, "NEAREST_LINE_STY", null, null, false);

Так как вы добавляете только PIN и линейные объекты к новой карте, то расточительно повторно генерировать все это хозяйство. Поэтому вы просто используете предыдущую карту как фон, временно дезактивируя все другие темы, и выдаете запрос к карте таким образом:

if(mv.getBackgroundImageURL()==null) mv.setBackgroundImageURL( mv.getGeneratedMapImageURL()); String[] enabledThemes = mv.getEnabledThemes(); mv.setAllThemesEnabled(false); //temporarily disable themes mv.run(); // reissue map request to // draw PIN and line

Как только вы сгенерируете новую карту, вы повторно активируете темы и убираете PIN и линейные объекты:

mv.enableThemes(enabledThemes); mv.removeAllPointFeatures(); // clean up the PIN marker mv.removeAllLinearFeatures(); // clean up leader line as well

И теперь у вас есть новая карта, получите атрибуты ближайшего офиса, и она готова к представлению информации.

Представление результирующей страницы

Секция представления результирующей страницы файла main.jsp содержит простые HTML-тэги. Инструментальная панель показана в листинге 3.

Код листинга 3: Представление инструментальной панели результирующей страницы

<!-- Left column : toolbar and map image --> <TD width="<%=width%>" bgcolor="#d4d0c8"> <% // pick up the correct icon file for the toolbar buttons String[] toolbarNames = new String[]{"zoomin", "pan", "zoomout", "zoombox", "id"}; String[] toolbarImgs = new String[toolbarNames.length]; for(int i=0; i<toolbarImgs.length; i++) { if(toolbarNames[i].equals(action)) toolbarImgs[i] = "myicons/" + toolbarNames[i] + "_dn.png"; else toolbarImgs[i] = "myicons/"+toolbarNames[i]+".png"; } %> <%@ include file="toolbar.html" %> </TD>



Предложение <%@ include file="toolbar.html" %> определяет положение кнопок инструментальной панели. Для каждой кнопки должен быть выбран реальный файл-иконка, способный отображать текущий статус кнопки (то есть, щелкнули по ней или нет). JSP-код в листинге 3 в цикле обрабатывает список имен кнопок и выбирает из директории myicons нужный файл для кнопочной иконки. Если по кнопке, такой как "pan," щелкнули, вы используете файл <button_name>_dn.png (в данном случае pan_dn.png). Имена этих файлов собраны в файле toolbar.html file.

Представление изображения сгенерированной карты

Код листинга 4 представляет изображение сгенерированной карты.

Код листинга 4: Представление карты

<% // Get the HTML AREA definition of selected theme's Image Map. String areas = clkmv.getThemeAsHTMLAreas( "FIELD OFFICE CLK", true) ; %> <MAP NAME="omv_infomap">

<%= areas==null?"":areas %> </MAP> <div id="infotip_window"></div> <div id="display" style="position:relative"> <!? now for the actual map image --> <img id="oramap" src="<%=mv.getGeneratedMapImageURL()%>" border="1" usemap="#omv_infomap" onload="changeActionButton('<%=action%>')" /> </div> <div id="tbar_rect"></div>

Этот код - по существу HTML-тэг <img> с src-изображением, полученным от mv по методу getGeneratedMapImageURL(). Он использует HTML-изображение карты с названием omv_infomap, контент которой возвращается от метода call getThemeAsHTMLAreas() от clkmv и размещается между тэгом <MAP> и тэгом <img> . Наконец, тэг <img> окружается различными элементами типа <DIV>, включая infotip_window и tbar_rect, для дополнительного окна и изменения масштаба (box-based zoom), соответственно.

Когда MapViewer представляет изображение карты, пользователь может щелкнуть по навигационным кнопкам карты ("pan" или "zoom") или по карте для идентификации показанной особенности. Так как некоторая информация состояния или значения параметров должны сохраняться между запросами, то HTML FORM содержит текущие значения параметров. Когда пользователь щелкает по карте, функция JavaScript использует эти параметры для выдачи нового запроса к карте.


Содержание раздела