The code is tested for Oracle 11g, but should work equally well for Oracle XE (no advanced Spatial operations), although I have noticed that Oracle XE is a bit more picky when it comes to valid shapes.
Demo Application
If there is too much text for you to read through, check out my demo Application on apex.oracle.com to see it in action :-)
The demo application is tested on Firefox ONLY, so expect issues when using other browsers!
Database objects
The code below will create a simple table with one column containing a sdo_geometry column called shapes, and a supporting package to mediate between APEX/Google Maps and the database table:
create table sample_polygon ( sample_polygon_id number not null , name varchar2 (80) not null , description varchar2 (4000) , zoom_level number , shape mdsys.sdo_geometry ) / alter table sample_polygon add ( constraint sample_polygon_pk primary key (sample_polygon_id)) / create sequence sample_polygon_pk_seq / create or replace trigger trg_sample_polygon_bi before insert on sample_polygon referencing new as new old as old for each row declare l_new_id number; begin if :new.sample_polygon_id is null then select sample_polygon_pk_seq.nextval into l_new_id from dual; :new.sample_polygon_id := l_new_id; end if; exception when others then raise; end trg_sample_polygon_bi; / create or replace package sample_polygon_p as -- return string with coordinates function get_ordinates ( p_shape in sample_polygon.shape%type ) return varchar2; -- update table with shape procedure create_geometry ( p_sample_polygon_id in sample_polygon.sample_polygon_id%type , p_name in sample_polygon.name%type , p_description in sample_polygon.description%type , p_zoom_level in sample_polygon.zoom_level%type , p_shape in varchar2); end; / create or replace package body sample_polygon_p as function get_ordinates ( p_shape in sample_polygon.shape%type ) return varchar2 is l_poly mdsys.sdo_ordinate_array; l_coords varchar2(4000); l_point varchar2(20); begin l_poly := p_shape.sdo_ordinates; if l_poly.exists(1) then for i in l_poly.first..l_poly.last loop l_coords := l_coords ||','||replace(l_poly(i), ',', '.'); end loop; l_coords := substr(l_coords, 2, length(l_coords)); end if; return l_coords; end; procedure create_geometry ( p_sample_polygon_id in sample_polygon.sample_polygon_id%type , p_name in sample_polygon.name%type , p_description in sample_polygon.description%type , p_zoom_level in sample_polygon.zoom_level%type , p_shape in varchar2 ) is l_sql varchar2(32000); l_sample_polygon_id sample_polygon.sample_polygon_id%type := p_sample_polygon_id; begin if l_sample_polygon_id is null then insert into sample_polygon ( name , description , zoom_level ) values ( p_name , p_description , p_zoom_level) returning sample_polygon_id into l_sample_polygon_id; else update sample_polygon set name = p_name , description = p_description , zoom_level = p_zoom_level where sample_polygon_id = l_sample_polygon_id; end if; -- 2003: Two dimentional polygon -- 4326: SRID -- 1,1003,1: one polygon (exterior polygon ring) l_sql := 'update sample_polygon'||chr(10)|| 'set shape = sdo_geometry (2003'||chr(10)|| ' , ''4326'''||chr(10)|| ' , null'||chr(10)|| ' , sdo_elem_info_array(1,1003,1)'||chr(10)|| ' , sdo_ordinate_array( '|| p_shape ||')'||chr(10)|| ' )'||chr(10)|| 'where sample_polygon_id = :1'; execute immediate l_sql using in l_sample_polygon_id; end; end; /You must have Oracle Spatial installed in your database (is part of default installation, including XE), and schema must have appropriate rights to invoke Spatial functions. If the above script delivers no error-messages you should be OK.
Why Spatial?
Well, why not? You already paid for it in you license, and quite frankly I can see no easier way to store your shapes. There are also a number of valuable functions that comes with Spatial, such as:
- Location inside shape
- Distance to nearest part of shape from location
- Conversion between coordinate types
- The ability to view shapes in other client tools like ESRI
I have very limited experience with Oracle Spatial, and the syntax for creating shapes as an SDO_GEOMETRY-data type was (is) a bit daunting.
Lessons learned are:
Take a close look at which coordinate system you are storing the points in. I have used the most common 4326, but if I understood correctly Google actually uses 3857 or 900913. This requires some further investigation.
The Google Maps API
There are already some examples on how to integrate Oracle APEX and Google Maps, and likewise, there are many examples on how to interact with Google Maps using the Google Maps API. I will list some of the resources on the subject:
- Official Oracle APEX/Google Maps integration written by Jason Straub
- Collection of map integrations with Oracle APEX by Patrick Wolf
- Google Maps API Tool by Kjell Scharning
- Official Google Maps API Reference
The first thing to do when trying out this code, is to sign up and get a Google Maps API Key!
A tiny bit of Javascript
The meaning of "tiny" being somewhat stretched here. Even if you are not familiar with Javascript, it is surprisingly easy to pick up. This script might not be the best place to start, but I encourage you to look at the source code from my demo application in detail to see what it does.
I will not do a full listing here, but highlight some of the more important functions and give a brief top-down view of what goes on.
On page rendering:
- Javascript function buildMap is called
- Invokes Google Maps API
- Draws a map
- Adds onClick-listener to the map to enable the user to create shapes
On click in map:
- Draws a new marker on the map
- Adds a new point to points array (this is what gets stored in the database)
- Redraws the polygon on the map
On click on a marker in the map
- Removes the marker
- Removes the point from the points array
- Redraws the map
Edit mode:
- Redraws map to ensure completeness of polygon
- Removes markers
- Makes polygon editable
- Removes onClick-listener on Map (Adding new points/markers in the map is no longer possible)
Exit edit mode:
- Repopulates points array from polygon
- Makes polygon uneditable (is that even a word?)
- Redraws polygon on map with markers
Create new shape:
- Removes all overlays from map (markers and polygon)
- Resets all arrays and variables
- Reattaches onClick-listener to map
For more details, you have to dig into the source code (view source in the demo application).
Merging Oracle Spatial and Google Maps
This not advanced mathematics, I have two functions in the database:
- One which extracts ordinates (as they are called, don't ask me why) from the stored SDO_GEOMETRY-object, and return the ordinates as a comma-separated string
- One which accepts a shape as a comma-separated string and creates a SDO_GEOMETRY-object
I also have two javascript functions:
- One which accepts a string of comma separated coordinates, splits it into an array og "Google points"
- One which accepts an array of "Google points", and returns a comma separated string (well, not exactly, it "returns" by setting an APEX item...)
Bringing it All Together
Oracle Apex is the glue between Google Maps and Oracle Spatial, but the actual coding in APEX to achieve this is quite little.
In my demo application I have:
- Region containing a DIV and all necessary Javascrips to show and interact with Google Maps
- Region based on a stored procedure to store shapes
- Region containing a report of stored shapes
That's it, enjoy :-)
Hi,
ReplyDeletehave you thought about creating a region plug-in the map integration? That would allow to easier integrate it into an application in APEX 4.0?
Regards
Patrick
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download Now
Delete>>>>> Download Full
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download LINK
>>>>> Download Now
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download Full
>>>>> Download LINK G7
Interesting post, as always! :-)
ReplyDelete@Patrick
ReplyDeleteGood idea! I haven't really had much time to Apex 4.0 yet, but reading your tutorials on how to create plug-ins are on the roster :-) The Javascripts needs to be cleaned up and made more robust first though...
@Morten
Thanks, and right back at you! Using SQL*Plus to translate, that's what I call stepping back into the future :-) Great work!
Hello,
ReplyDeleteGoogle introduced Google Maps API V3 recently.
And according to the documentation (http://code.google.com/intl/nl/apis/maps/documentation/v3/): This version of the Google Maps JavaScript API no longer needs API keys!
Not every piece of V2 functionality is implemented in V3 yet. V3 is designed for fast loading, think of mobile devices.
With kind regards,
Jornica
Havard, Great post and example...but where is your Apex code
ReplyDeleteThanks
Marc
Great post
ReplyDeleteCan you tell me what the application processes do
dummyProc and getPoints
@Marc
ReplyDeleteNot much in the page, apart from the one below.
@pjflynn
I had a bit of a rewrite when upgrading to apex 4, and, ah well.. The whole page is a bit messy by now.
dummyProc does not exist, it is only to set page session variables.
getPoints is an Ajax callback located on the same page and looks like this:
declare
l_shape_id number := wwv_flow.g_x01;
l_shape sdo_geometry;
l_description sample_polygon.description%type;
l_name sample_polygon.name%type;
begin
select shape, description, name
into l_shape, l_description, l_name
from sample_polygon
where sample_polygon_id = l_shape_id;
owa_util.mime_header (
'text/xml'
, false
);
htp.p ('Cache-Control: no-cache');
htp.p ('Pragma: no-cache');
owa_util.http_header_close;
htp.prn ('<xmlWrapper>');
htp.prn ('<getPointVals>');
htp.prn (sample_polygon_p.get_ordinates(l_shape));
htp.prn ('</getPointVals>');
htp.prn ('<polyDescription>'||l_description||'</polyDescription>');
htp.prn ('<polyName>'||l_name||'</polyName>');
htp.prn ('</xmlWrapper>');
end;
Great Post.
ReplyDeleteWe can download the code ....?
Thanks
svrobot@gmail.com
it's a great form, but how can i do it in my Apex application? please support
ReplyDeleteshaddad.m@extra.com
The TalkTalk mail login issues are often seen due to the internet connectivity problem or the issues of wrong login credentials, in such cases, it is advisable that the user gets connected with the team of trained and certified TalkTalk experts lines are open for help and support of the users all the time there is no such issue that cannot be resolved by the Talktalk experts lines are kept open for help all the time.
ReplyDeleteTalkTalk Mail Help Number UK.
The process of creating a group Gmail account is very easy for that one should open the Google group website on the browser and should click the option “create group” further a name for the group should be entered and the email address that is to be used a group description should be added, for knowing anything further regarding the process one can ring the experts at +44-800-368-9067.
ReplyDeleteGmail Phone Number UK
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download Now
ReplyDelete>>>>> Download Full
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download LINK
>>>>> Download Now
Monkey On Oracle: Oracle Spatial, Apex And Google Maps >>>>> Download Full
>>>>> Download LINK oO