Skip to Main Content
Ted Struik - Oracle
Search For
Home
Home
Ted Struik - Oracle
Search
Site Map
Statistics
Page Errors
Apex
Apex
General
Autocomplete
Conditions
Errors
Items used in PL/SQL
Validations
Dynamic Actions
Logs
Version
App-wide Items
Error Handling
Apex Views
Apex Upgrade 4.2 to 5.1
Apex Upgrade 20.2 to 23.1
Database Dependencies
Show Source Code
URLs
Authorization
Modal Dialogs
Apex Office Print (AOP)
Apex-Sert
Warn on Unsaved Changes
Form Regions
Reports
Checkboxes
Download
Errors
Nowrap Columns
Substitution Strings
Use IR results in pl/sql
Clickable Row
Row Highlight
Translate Filters etc.
Bar Charts
Column Usage
Reset Pagination
Hide IR Actions menu items
Get Classic Report query
Interactive Grid
ORA-20987
ERR-1002
Copying Text
IG Info
Multiple Row Select
Read Only Options
Search
Sort and Search
Images & Fonts
Standard Icons & Fonts
WebDav
Font Awesome
Icons/image popup LOV
Lists
Hierarchy
LOVs
Definition Bug
Set 1-item LOV to Disabled
With Clause Errors
Modal LOV Plugin
HTML / CSS / JavaScript
Vertical Align
Legend CSS
Geolocation
Apex.confirm
Pie Charts
Codemirror
Theme Roller
Catching Key Strokes
Browser Cache
Locale
RequireJS
Collapsible Regions
Find JavaScript
Import / Export
Dynamic Translations
Translated Pages
APEXExport (java)
apex_export (pl/sql)
Component Settings
Charts
Translate Charts
[Reports] Bar Charts
Shuttles
Shuttle Sorting
Disable Shuttle Items
Menus
Accordion-Like
Scroll bug
Authorization
Session State
About Session State
Rollback & Commit
Performance of v()
Apex Clone Session
Request
Session State in Views
Collections
ORA-20101 & ORA-20104
ORA-00001
Max Row Count
(PL)SQL
(PL)SQL
External Tables
SQL Plus
Conditions
Long
ORDImage
Date & Timestamp
CGI environment
Sys_context
Rounding percentages
Apex_string.split in SQL
Dbms_metadata
Instr
Regular Expressions
Rollback to Savepoint
Use table aliases
(Pipelined) Bulk Collect
JSON
Source Code Search (PL/SQL)
Source Code Search (SQL)
Format Models
Pipelined Table Functions
Hint no_unnest
Listagg
DBA
DBA
Backup & Restore
Users
Export & Import
DBMS Jobs
Tablespaces
Table Size
Flush cache
Access Control List (ACL)
Locks
Java
Constraints
Object Dependencies
Package Dependencies 1
Package Dependencies 2
Grants
SQL History
Startup Errors
ORDS
Miscellaneous
Miscellaneous
Holidays
E-mail
NLExtract
Windows
VPN
VMware
Links
Google
Visualization Orgchart
Hide Search Results
Reverse Proxy
To-do List
Cytoscape
Graphics
Upscaling
Amazon Prices
Domoticz
DDoS
Hobbies
Hobbies
Motorcycles
'95 Kawasaki ZZR 600
'94 Kawasaki ZZR 1100
'91 Honda CBR 600 F2
'95 Kawasaki ZZR 1100
'99 Honda CBR 1100 XX
'00 Honda CBR 1100 XX
'02 Kawasaki ZX-12R (NL)
'05 Ducati 999 (NL)
'08 Honda Fireblade
'07 Suzuki Bandit 1250A
'18 Suzuki GSX-S 1000 F
MotoGP
Garfield
Lyrics
Skydive
Woodworking
Pantorouter
16 inch Bandsaw
Introduction
Frame
Wheels
Wheel mounts
Blade guides
Trunions and table
Enclosure
Alignment and more
Box Joint Jig
Foldable Sawhorses
Strip Sander XL
Photography
Sony RX10 IV
Yes Minister
WinAmp
Skydive
Location
NL - Teuge - De Bak
NL - Teuge - Het Kussen
NL - Ameland - Beachclub The Sunset
NL - Eelde - Vliegveld
NL - Texel - Grindbak
NL - Texel - Veld
F - Gap
F - Le Luc
USA - San Diego
VAE - Dubai - Zero Gravity
Wind Direction @ groud
0 - North
10
20
30
40
50
60
70
80
90 - East
100
110
120
130
140
150
160
170
180 - South
190
200
210
220
230
240
250
260
270 - West
280
290
300
310
320
330
340
350
Wind Speed @ ground
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
knots
Info
Beta version - use at your own risk!
A first take at plotting a skydive landing pattern onto Google Maps.
Calculations are for 3 stages of 300 feet each.
This is not my hobby! It's Barbara's :-)
Thanks to Marc for providing the Excel sheet that inspired this!
Another great implementation of this idea:
Blue Skies
More info on weather and wind:
Jumprun.nl
Locations
Id
Name
Lat
Lng
1
NL - Teuge - De Bak
52.246511
6.049092
2
NL - Teuge - Het Kussen
52.246789
6.045298
3
NL - Ameland - Beachclub The Sunset
53.4496604
5.6142207
4
NL - Texel - Veld
53.11925176
4.830363607
5
NL - Texel - Grindbak
53.11825203
4.829039776
1 - 5
Next
Code
Table
Table
Name
TED_SKYDIVE_LOCATIONS
DDL
CREATE TABLE "TEDSTRUIK"."TED_SKYDIVE_LOCATIONS" ( "ID" NUMBER NOT NULL ENABLE, "NAME" VARCHAR2(1000) NOT NULL ENABLE, "LAT" NUMBER NOT NULL ENABLE, "LNG" NUMBER NOT NULL ENABLE ) SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" CREATE UNIQUE INDEX "TEDSTRUIK"."SLN_PK" ON "TEDSTRUIK"."TED_SKYDIVE_LOCATIONS" ("ID") PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ALTER TABLE "TEDSTRUIK"."TED_SKYDIVE_LOCATIONS" ADD CONSTRAINT "SLN_PK" PRIMARY KEY ("ID") USING INDEX "TEDSTRUIK"."SLN_PK" ENABLE
Item
Identification
Sequence
10
Name
P1093_LOCATION_ID
Display As
Select List
User Interface
Region
Skydive
List Of Values
Display Extra Values
Yes
Display Null Value
No
List of values definition
select name as d , id as r from ted_skydive_locations order by ( case when name like 'NL - Teuge%' then 1 when name like 'NL%' then 2 else 3 end ) , name
Item
Identification
Sequence
20
Name
P1093_WIND_ANGLE
Display As
Select List
User Interface
Region
Skydive
List Of Values
Display Extra Values
Yes
Display Null Value
No
List of values definition
select trim(a) || ( case a when 0 then ' - North' when 90 then ' - East' when 180 then ' - South' when 270 then ' - West' else '' end ) as d , a as r from ( select (level-1)*10 as a from dual connect by level <= 36 ) order by a
Item
Identification
Sequence
30
Name
P1093_WIND_SPEED
Display As
Select List
User Interface
Region
Skydive
List Of Values
Display Extra Values
Yes
Display Null Value
No
List of values definition
select trim(a) as d , a * 0.5144 as r from ( select level-1 as a from dual connect by level <= 21 ) order by a
Package
Package
Name
TED_P1093
Source
package ted_p1093 is -- constants c_lf constant varchar2(2) := chr(10); c_pi constant number := 3.141592653589793238462643383279502884197169399375; function js_map ( p_location_id in ted_skydive_locations.id%type , p_wind_speed in number -- meters per second , p_wind_angle_deg in number -- wind direction in degrees (Note: 0 = north, 90 = east) ) return varchar2 ; end ted_p1093;
Package Body
Package Body
Name
TED_P1093
Source
package body ted_p1093 is procedure vector ( po_lat in out number , po_lng in out number , p_distance_m in number -- distance in meters , p_angle in number -- angle in radians ) is c_r_earth constant number := 6378 * 1000; v_lat_old number := po_lat; v_lng_old number := po_lng; v_lat_m number; -- latitude change in meters v_lng_m number; -- longitude change in meters begin v_lat_m := p_distance_m * cos( p_angle + c_pi / 2 ); v_lng_m := p_distance_m * sin( p_angle + c_pi / 2 ); -- Source: http://stackoverflow.com/questions/7477003/calculating-new-longtitude-latitude-from-old-n-meters -- Not exact, but close enough for these purposes po_lat := v_lat_old + (v_lat_m / c_r_earth) * (180 / c_pi); po_lng := v_lng_old + (v_lng_m / c_r_earth) * (180 / c_pi) / cos(v_lat_old * c_pi / 180); end vector; function js_map ( p_location_id in ted_skydive_locations.id%type , p_wind_speed in number -- meters per second , p_wind_angle_deg in number -- wind direction in degrees (Note: 0 = north, 90 = east) ) return varchar2 is v_result varchar2(32767); v_loc_row ted_skydive_locations%rowtype; c_api_key constant varchar2(100) := 'AIzaSyB4wjotbHWx2NDxuaHbKNXNJTzSSg01Q0E'; c_forward_speed constant number := 10; -- meter per second -- # voorwaardse snelheid c_vector_secs constant number := 18; -- seconds per vector (18 seconds per 300 ft) -- # daalsnelheid (per 300 ft) v_wind_angle number := -1 * ( (p_wind_angle_deg+90) * c_pi / 180 ); -- wind direction converted to radials (Note: 0 = north, 90 = east) v_right_angled_to_downwind number := atan( p_wind_speed / c_forward_speed ); -- # hoek om haaks op downwind te vliegen (rad) v_right_angled_to_downwind_deg number := round( v_right_angled_to_downwind / c_pi * 180 ); -- # hoek om haaks op downwind te vliegen (deg) - used for debugging only v_dissolved_wind_on_base number := round( sin(v_right_angled_to_downwind) * p_wind_speed ); -- # ontbonden wind op base leg v_forward_speed_on_downwind number := round( c_forward_speed + p_wind_speed ); -- # voorwaartse snelheid op downwind v_forward_speed_on_base number := round( c_forward_speed - v_dissolved_wind_on_base ); -- # voorwaartse snelheid op base leg v_forward_speed_on_final number := round( c_forward_speed - p_wind_speed ); -- # voorwaartse snelheid op final v_dist_downwind number := round( v_forward_speed_on_downwind * c_vector_secs ); -- # wind afstand - downwind v_dist_base number := round( v_forward_speed_on_base * c_vector_secs ); -- # wind afstand - base v_dist_final number := round( v_forward_speed_on_final * c_vector_secs ); -- # wind afstand - final v_lat_temp number; v_lng_temp number; v_lat_temp_prev number; v_lng_temp_prev number; function number_to_char ( p_number in number ) return varchar2 is v_result varchar2(100); begin v_result := to_char(round(p_number,6), 'fm9990D999999', 'nls_numeric_characters = ''.,'''); return v_result; end number_to_char; begin select * into v_loc_row from ted_skydive_locations where id = p_location_id ; v_result := c_lf; v_result := v_result || '<script type="text/javascript" src="https://maps.google.com/maps/api/js?key='||c_api_key||'&sensor=false"></script>' || c_lf; v_result := v_result || '<script type="text/javascript">' || c_lf; v_result := v_result || ' var geocoder = new google.maps.Geocoder();' || c_lf; v_result := v_result || ' var myLatlng = new google.maps.LatLng(0,0);' || c_lf; v_result := v_result || ' var myOptions = {' || c_lf; v_result := v_result || ' zoom: 12' || c_lf; v_result := v_result || ' , center: myLatlng' || c_lf; v_result := v_result || ' , mapTypeId: google.maps.MapTypeId.SATELLITE' || c_lf; v_result := v_result || ' , scaleControl: true' || c_lf; v_result := v_result || ' }' || c_lf; v_result := v_result || ' var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);' || c_lf; v_result := v_result || ' var bounds = new google.maps.LatLngBounds();' || c_lf; v_result := v_result || ' var myLatlng = new google.maps.LatLng('||number_to_char(v_loc_row.lat)||', '||number_to_char(v_loc_row.lng)||');' || c_lf; v_result := v_result || ' var marker = new google.maps.Marker({' || c_lf; v_result := v_result || ' position: myLatlng' || c_lf; v_result := v_result || ' , map: map' || c_lf; v_result := v_result || ' , title: "'||v_loc_row.name||'"' || c_lf; v_result := v_result || ' });' || c_lf; v_result := v_result || ' bounds.extend(myLatlng);' || c_lf; -- vectors declare cursor c1 is select 1 as n , 900 as feet , 'final' as title , v_dist_final as distance , -1 * v_wind_angle as angle -- -1 because final approach is against the wind from dual union all select 2 as n , 600 as feet , 'base' as title , v_dist_base as distance , -1 * v_wind_angle + (c_pi / 2) as angle from dual union all select 3 as n , 300 as feet , 'downwind' as title , v_dist_downwind as distance , -1 * v_wind_angle + c_pi as angle from dual ; begin -- markers v_lat_temp := v_loc_row.lat; v_lng_temp := v_loc_row.lng; for c1_rec in c1 loop vector ( po_lat => v_lat_temp , po_lng => v_lng_temp , p_distance_m => c1_rec.distance , p_angle => c1_rec.angle ) ; v_result := v_result || ' var myLatlng = new google.maps.LatLng('||number_to_char(v_lat_temp)||', '||number_to_char(v_lng_temp)||');' || c_lf; v_result := v_result || ' var marker = new google.maps.Marker({' || c_lf; v_result := v_result || ' position: myLatlng' || c_lf; v_result := v_result || ' , map: map' || c_lf; v_result := v_result || ' , title: "'||c1_rec.title||'"' || c_lf; v_result := v_result || ' });' || c_lf; v_result := v_result || ' bounds.extend(myLatlng);' || c_lf; end loop; v_result := v_result || ' map.fitBounds(bounds);' || c_lf; -- arrows v_lat_temp := v_loc_row.lat; v_lng_temp := v_loc_row.lng; -- v_result := v_result || ' var lineSymbol = {' || c_lf; v_result := v_result || ' path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,' || c_lf; v_result := v_result || ' strokeColor: "#F00"' || c_lf; v_result := v_result || ' };' || c_lf; -- for c1_rec in c1 loop v_lat_temp_prev := v_lat_temp; v_lng_temp_prev := v_lng_temp; vector ( po_lat => v_lat_temp , po_lng => v_lng_temp , p_distance_m => c1_rec.distance , p_angle => c1_rec.angle ) ; v_result := v_result || ' var line = new google.maps.Polyline({' || c_lf; v_result := v_result || ' path: [{lat: '||number_to_char(v_lat_temp)||', lng: '||number_to_char(v_lng_temp)||'}' || ', {lat: '||number_to_char(v_lat_temp_prev)||', lng: '||number_to_char(v_lng_temp_prev)||'}],' || c_lf; v_result := v_result || ' strokeColor: "#F00",' || c_lf; v_result := v_result || ' icons: [{' || c_lf; v_result := v_result || ' icon: lineSymbol,' || c_lf; v_result := v_result || ' offset: "100%"' || c_lf; v_result := v_result || ' }],' || c_lf; v_result := v_result || ' map: map' || c_lf; v_result := v_result || ' });' || c_lf; end loop; end; v_result := v_result || '</script>' || c_lf; return v_result; end js_map; end ted_p1093;