summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McIntosh <ian_mcintosh@linuxadvocate.org>2005-10-11 18:28:45 +0000
committerIan McIntosh <ian_mcintosh@linuxadvocate.org>2005-10-11 18:28:45 +0000
commit488a4cd652a42e09058fd4b589086677e49547de (patch)
tree688fff2bd4b570c48f4c89cd66a0c476c089bfaf
parent7ae9d377f0993dfc08a3503b4e91c0bfb45ea283 (diff)
Added to test polygon point reduction algorithm and others.
Prepare for rectangle clipping. Add Douglas-Peucker point simplification algorithm. Add point distance from line function. Add in/out/partial rect overlap function.
-rw-r--r--ChangeLog7
-rw-r--r--data/layers.xml44
-rw-r--r--data/roadster.glade460
-rw-r--r--src/Makefile.am5
-rw-r--r--src/gui.c13
-rw-r--r--src/main.h2
-rw-r--r--src/mainwindow.c5
-rw-r--r--src/map.c2
-rw-r--r--src/map_draw_gdk.c146
-rw-r--r--src/map_hittest.c2
-rw-r--r--src/map_math.c178
-rw-r--r--src/map_math.h12
-rw-r--r--src/test_poly.c209
-rw-r--r--src/test_poly.h31
14 files changed, 932 insertions, 184 deletions
diff --git a/ChangeLog b/ChangeLog
index 3a53757..509539f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-10-11 Ian McIntosh <ian_mcintosh@linuxadvocate.org>
+
+ * src/test_poly.c:
+ * src/test_poly.h: Added to test polygon point reduction algorithm and others.
+ * src/map_draw_gdk.c: Prepare for rectangle clipping.
+ * src/map_math.c: Add Douglas-Peucker point simplification algorithm. Add point distance from line function. Add in/out/partial rect overlap function.
+
2005-10-10 Ian McIntosh <ian_mcintosh@linuxadvocate.org>
* data/layers.xml:
diff --git a/data/layers.xml b/data/layers.xml
index 9f43dfd..56825ad 100644
--- a/data/layers.xml
+++ b/data/layers.xml
@@ -39,8 +39,8 @@
</layer>
<layer data-source="parks" draw-type="polygon-labels">
- <property zoom-level="6" name="font-size" value="10" />
- <property zoom-level="7" name="font-size" value="10" />
+<!-- <property zoom-level="6" name="font-size" value="10" /> -->
+ <property zoom-level="7" name="font-size" value="9" />
<property zoom-level="8" name="font-size" value="11" />
<property zoom-level="9" name="font-size" value="12" />
<property zoom-level="10" name="font-size" value="22" />
@@ -50,8 +50,8 @@
</layer>
<layer data-source="lakes" draw-type="polygon-labels">
- <property zoom-level="5" name="font-size" value="9" />
- <property zoom-level="6" name="font-size" value="9" />
+<!-- <property zoom-level="5" name="font-size" value="9" /> -->
+ <property zoom-level="6" name="font-size" value="9" />
<property zoom-level="7" name="font-size" value="9" />
<property zoom-level="8" name="font-size" value="10" />
<property zoom-level="9" name="font-size" value="11" />
@@ -62,9 +62,9 @@
</layer>
<layer data-source="misc-areas" draw-type="polygon-labels">
- <property zoom-level="6" name="font-size" value="10" />
- <property zoom-level="7" name="font-size" value="12" />
- <property zoom-level="8" name="font-size" value="13" />
+<!-- <property zoom-level="6" name="font-size" value="10" /> -->
+ <property zoom-level="7" name="font-size" value="10" />
+ <property zoom-level="8" name="font-size" value="11" />
<property zoom-level="9" name="font-size" value="14" />
<property zoom-level="10" name="font-size" value="24" />
<property zoom-level="6-10" name="color" value="#303030FF" />
@@ -151,26 +151,26 @@
</layer>
<layer data-source="minor-highway-ramps" draw-type="lines">
<!-- minor highway ramp top -->
- <property zoom-level="8" name="line-width" value="3" />
- <property zoom-level="9" name="line-width" value="5" />
+ <property zoom-level="8" name="line-width" value="1" />
+ <property zoom-level="9" name="line-width" value="5" />
<property zoom-level="10" name="line-width" value="8" />
- <property zoom-level="6-10" name="color" value="#fffbffff" />
+ <property zoom-level="8-10" name="color" value="#fffbffff" />
</layer>
<layer data-source="minor-roads" draw-type="lines">
<!-- minor roads top -->
<property zoom-level="7" name="line-width" value="1" />
- <property zoom-level="7" name="color" value="#CAC2A9ff" />
+ <property zoom-level="7" name="color" value="#D9D0B7ff" />
<property zoom-level="7" name="line-cap" value="square" />
- <property zoom-level="8" name="line-width" value="1" />
+ <property zoom-level="8" name="line-width" value="2" />
<property zoom-level="9" name="line-width" value="10" />
<property zoom-level="10" name="line-width" value="18" />
<property zoom-level="8-10" name="color" value="#FFFFFFFF" />
</layer>
<layer data-source="minor-highway-ramps" draw-type="lines">
<!-- minor highway ramps top -->
- <property zoom-level="8" name="line-width" value="5" />
+ <property zoom-level="8" name="line-width" value="3" />
<property zoom-level="9" name="line-width" value="7" />
<property zoom-level="10" name="line-width" value="10"/>
<property zoom-level="7-10" name="color" value="#c0c0c0ff" />
@@ -190,11 +190,13 @@
<layer data-source="minor-roads" draw-type="lines">
<!-- minor roads bottom -->
- <property zoom-level="8" name="line-width" value="3" />
+ <property zoom-level="8" name="line-width" value="4" />
<property zoom-level="8" name="line-cap" value="square" />
- <property zoom-level="9" name="line-width" value="12" />
+ <property zoom-level="8" name="color" value="#D5CEB4ff" />
+
+ <property zoom-level="9" name="line-width" value="12" />
<property zoom-level="10" name="line-width" value="20" />
- <property zoom-level="8-10" name="color" value="#C5BEA4ff" />
+ <property zoom-level="9-10" name="color" value="#C5BEA4ff" />
</layer>
<layer data-source="railroads" draw-type="lines">
@@ -227,7 +229,11 @@
</layer>
<layer data-source="lakes" draw-type="polygons">
- <property zoom-level="1-10" name="color" value="#B5C6D6FF" />
+ <property zoom-level="1-10" name="color" value="#B6CCDEFF" />
+ </layer>
+ <layer data-source="lakes" draw-type="lines">
+ <property zoom-level="1-10" name="line-width" value="2" />
+ <property zoom-level="1-10" name="color" value="#9Db6bEFF" />
</layer>
<layer data-source="parks" draw-type="polygons">
@@ -235,8 +241,8 @@
<property zoom-level="1-10" name="color" value="#DEDBADff" />
</layer>
<layer data-source="parks" draw-type="lines">
- <property zoom-level="1-10" name="line-width" value="2" />
- <property zoom-level="1-10" name="color" value="#BEBB8Dff" />
+ <property zoom-level="1-10" name="line-width" value="2" />
+ <property zoom-level="1-10" name="color" value="#BEBB8Dff" />
</layer>
<layer data-source="misc-areas" draw-type="polygons">
diff --git a/data/roadster.glade b/data/roadster.glade
index 2178663..7736b07 100644
--- a/data/roadster.glade
+++ b/data/roadster.glade
@@ -1139,7 +1139,7 @@ Banks</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image10265">
+ <widget class="GtkImage" id="image10292">
<property name="visible">True</property>
<property name="stock">gtk-open</property>
<property name="icon_size">1</property>
@@ -1172,7 +1172,7 @@ Banks</property>
<property name="use_underline">True</property>
<child internal-child="image">
- <widget class="GtkImage" id="image10266">
+ <widget class="GtkImage" id="image10293">
<property name="visible">True</property>
<property name="stock">gtk-save-as</property>
<property name="icon_size">1</property>
@@ -1199,7 +1199,7 @@ Banks</property>
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10267">
+ <widget class="GtkImage" id="image10294">
<property name="visible">True</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">1</property>
@@ -1302,7 +1302,7 @@ Banks</property>
<property name="visible">True</property>
<property name="label" translatable="yes">_Auto</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
</widget>
</child>
@@ -1311,7 +1311,7 @@ Banks</property>
<property name="visible">True</property>
<property name="label" translatable="yes">_Day Colors</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">auto1</property>
</widget>
</child>
@@ -1370,7 +1370,7 @@ Banks</property>
<accelerator key="Left" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10268">
+ <widget class="GtkImage" id="image10295">
<property name="visible">True</property>
<property name="stock">gtk-go-back</property>
<property name="icon_size">1</property>
@@ -1393,7 +1393,7 @@ Banks</property>
<accelerator key="Right" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10269">
+ <widget class="GtkImage" id="image10296">
<property name="visible">True</property>
<property name="stock">gtk-media-forward</property>
<property name="icon_size">1</property>
@@ -1453,7 +1453,7 @@ Banks</property>
<accelerator key="F9" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10270">
+ <widget class="GtkImage" id="image10297">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
@@ -1501,7 +1501,7 @@ Banks</property>
<signal name="activate" handler="mainwindow_on_aboutmenuitem_activate" last_modification_time="Sat, 12 Mar 2005 06:48:18 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10271">
+ <widget class="GtkImage" id="image10298">
<property name="visible">True</property>
<property name="stock">gtk-about</property>
<property name="icon_size">1</property>
@@ -1553,7 +1553,7 @@ Banks</property>
<signal name="activate" handler="mainwindow_on_import_maps_activate" last_modification_time="Fri, 04 Mar 2005 04:28:20 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10272">
+ <widget class="GtkImage" id="image10299">
<property name="visible">True</property>
<property name="stock">gtk-open</property>
<property name="icon_size">1</property>
@@ -1581,7 +1581,7 @@ Banks</property>
<accelerator key="F5" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10273">
+ <widget class="GtkImage" id="image10300">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
@@ -1603,7 +1603,7 @@ Banks</property>
<accelerator key="F6" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10274">
+ <widget class="GtkImage" id="image10301">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
@@ -1623,6 +1623,15 @@ Banks</property>
</child>
<child>
+ <widget class="GtkMenuItem" id="polygon_test_window1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Polygon Test Window</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="test_poly_show" last_modification_time="Tue, 11 Oct 2005 21:37:38 GMT"/>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkImageMenuItem" id="gotomenuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">_GoTo Dialog</property>
@@ -1631,7 +1640,7 @@ Banks</property>
<accelerator key="g" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image10275">
+ <widget class="GtkImage" id="image10302">
<property name="visible">True</property>
<property name="stock">gtk-jump-to</property>
<property name="icon_size">1</property>
@@ -2055,151 +2064,127 @@ Banks</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
- <widget class="GtkVBox" id="mainwindowcontentsbox">
+ <widget class="GtkVBox" id="vbox8924">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
- <widget class="GtkToolbar" id="toolbar2">
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
- <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
- <property name="tooltips">False</property>
- <property name="show_arrow">True</property>
+ <widget class="GtkVPaned" id="vpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">100</property>
<child>
- <widget class="GtkToolItem" id="toolitem1">
- <property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
+ <widget class="GtkScrolledWindow" id="scrolledwindow9247">
+ <property name="height_request">100</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkButton" id="button44">
+ <widget class="GtkTreeView" id="directionstreeview">
<property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">False</property>
-
- <child>
- <widget class="GtkLabel" id="label92351">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;United States&lt;/b&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">8</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- </child>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">True</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">False</property>
+ <property name="fixed_height_mode">False</property>
+ <property name="hover_selection">False</property>
+ <property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
+ <property name="shrink">False</property>
+ <property name="resize">False</property>
</packing>
</child>
<child>
- <widget class="GtkToolItem" id="toolitem2">
+ <widget class="GtkVBox" id="mainwindowcontentsbox">
<property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
<child>
- <widget class="GtkButton" id="button45">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">False</property>
+ <widget class="GtkToolbar" id="toolbar2">
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+ <property name="tooltips">False</property>
+ <property name="show_arrow">True</property>
<child>
- <widget class="GtkLabel" id="label92353">
+ <widget class="GtkMenuToolButton" id="countrybutton">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;Massachusetts&lt;/b&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">8</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="label" translatable="yes">Country</property>
+ <property name="use_underline">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
</child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkToolItem" id="toolitem3">
- <property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
-
- <child>
- <widget class="GtkButton" id="button46">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">False</property>
+ <child>
+ <widget class="GtkMenuToolButton" id="statebutton">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">State</property>
+ <property name="use_underline">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
<child>
- <widget class="GtkLabel" id="label92352">
+ <widget class="GtkMenuToolButton" id="citybutton">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;Cambridge&lt;/b&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">8</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="label" translatable="yes">City</property>
+ <property name="use_underline">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
</child>
</widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
</child>
</widget>
<packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
-
- <child>
- <placeholder/>
- </child>
</widget>
</child>
</widget>
@@ -5569,4 +5554,249 @@ review</property>
</child>
</widget>
+<widget class="GtkWindow" id="test_polywindow">
+ <property name="width_request">300</property>
+ <property name="height_request">300</property>
+ <property name="title" translatable="yes">Polygon Reduction Test</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+
+ <child>
+ <widget class="GtkVBox" id="test_poly_contentbox">
+ <property name="border_width">4</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox103">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8926">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">4</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8927">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label92390">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Reduction Tolerance&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHScale" id="test_poly_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="draw_value">True</property>
+ <property name="value_pos">GTK_POS_LEFT</property>
+ <property name="digits">2</property>
+ <property name="update_policy">GTK_UPDATE_CONTINUOUS</property>
+ <property name="inverted">False</property>
+ <property name="adjustment">0.10000000149 0 1 0.00999999977648 0 0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8928">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label92391">
+ <property name="label" translatable="yes">&lt;b&gt;Smoothing&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHScale" id="hscale2">
+ <property name="can_focus">True</property>
+ <property name="draw_value">True</property>
+ <property name="value_pos">GTK_POS_LEFT</property>
+ <property name="digits">2</property>
+ <property name="update_policy">GTK_UPDATE_CONTINUOUS</property>
+ <property name="inverted">False</property>
+ <property name="adjustment">0.10000000149 0 1 0.00999999977648 0 0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator7">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">4</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="test_poly_clear_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkImage" id="image10281">
+ <property name="visible">True</property>
+ <property name="stock">gtk-clear</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame60">
+ <property name="border_width">2</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+
+ <child>
+ <widget class="GtkDrawingArea" id="test_polydrawingarea">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="test_polylabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label92389</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
</glade-interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index aa9c0a9..2056ead 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,10 +21,12 @@ roadster_SOURCES = \
main.c\
db.c\
downloadmanager.c\
+ directionswindow.c\
gui.c\
mainwindow.c\
gotowindow.c\
map.c\
+ mapinfowindow.c\
map_draw_cairo.c\
map_draw_gdk.c\
map_history.c\
@@ -50,7 +52,8 @@ roadster_SOURCES = \
road.c\
animator.c\
gfreelist.c\
- tooltipwindow.c
+ tooltipwindow.c\
+ test_poly.c
roadster_LDADD = \
$(GNOME_LIBS) \
diff --git a/src/gui.c b/src/gui.c
index ec56cb1..4c5910e 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -35,14 +35,21 @@
#include "gotowindow.h"
#include "importwindow.h"
#include "searchwindow.h"
+#include "mapinfowindow.h"
#include "locationeditwindow.h"
+#ifdef ENABLE_TEST_MODULES
+#include "test_poly.h"
+#endif
+
void gui_init(void)
{
GladeXML* pGladeXML = gui_load_xml(GLADE_FILE_NAME, NULL);
glade_xml_signal_autoconnect(pGladeXML);
// init all windows/dialogs
+ g_print("- initializing mapinfowindow\n");
+ mapinfowindow_init(pGladeXML);
g_print("- initializing mainwindow\n");
mainwindow_init(pGladeXML);
g_print("- initializing searchwindow\n");
@@ -51,6 +58,12 @@ void gui_init(void)
gotowindow_init(pGladeXML);
g_print("- initializing importwindow\n");
importwindow_init(pGladeXML);
+
+#ifdef ENABLE_TEST_MODULES
+ g_print("- initializing test_poly\n");
+ test_poly_init(pGladeXML);
+#endif
+
//datasetwindow_init(pGladeXML);
g_print("- initializing locationeditwindow\n");
locationeditwindow_init(pGladeXML);
diff --git a/src/main.h b/src/main.h
index bf7e5e7..8919d96 100644
--- a/src/main.h
+++ b/src/main.h
@@ -26,6 +26,8 @@
//#define G_DISABLE_ASSERT
+#define ENABLE_TEST_MODULES
+
#include <gtk/gtk.h>
#define USE_GNOME_VFS // comment this out to get a faster single-threaded compile (can't import, though)
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 68ddd51..8dc24a2 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -48,6 +48,7 @@
#include "glyph.h"
#include "animator.h"
#include "map_history.h"
+#include "mapinfowindow.h"
#include "tooltipwindow.h"
@@ -447,7 +448,7 @@ void mainwindow_init(GladeXML* pGladeXML)
g_signal_connect(G_OBJECT(g_MainWindow.pWindow), "window_state_event", G_CALLBACK(mainwindow_on_window_state_change), NULL);
g_signal_connect(G_OBJECT(g_MainWindow.pWindow), "key_press_event", G_CALLBACK(mainwindow_on_key_press), NULL);
g_signal_connect(G_OBJECT(g_MainWindow.pWindow), "key_release_event", G_CALLBACK(mainwindow_on_key_release), NULL);
-
+
// Drawing area
g_MainWindow.pDrawingArea = GTK_DRAWING_AREA(gtk_drawing_area_new());
@@ -494,6 +495,8 @@ void mainwindow_init(GladeXML* pGladeXML)
// XXX: move map to starting location... for now it's (0,0)
mainwindow_add_history();
mainwindow_update_zoom_buttons(); // make sure buttons are grayed out
+
+ mapinfowindow_update(g_MainWindow.pMap);
}
gboolean mainwindow_locationset_list_is_separator_callback(GtkTreeModel *_unused, GtkTreeIter *pIter, gpointer __unused)
diff --git a/src/map.c b/src/map.c
index 97e7ccf..a5a3f5a 100644
--- a/src/map.c
+++ b/src/map.c
@@ -158,7 +158,7 @@ gchar* g_apszMapRenderTypeNames[] = {"lines", "polygons", "line-labels", "polygo
// init the module
void map_init(void)
{
- g_print("*********************************** %f\n", WORLD_FEET_PER_DEGREE);
+ //g_print("*********************************** %f\n", WORLD_FEET_PER_DEGREE);
}
gboolean map_new(map_t** ppMap, GtkWidget* pTargetWidget)
diff --git a/src/map_draw_gdk.c b/src/map_draw_gdk.c
index 4a538e8..c972531 100644
--- a/src/map_draw_gdk.c
+++ b/src/map_draw_gdk.c
@@ -38,6 +38,7 @@
#include "db.h"
#include "road.h"
#include "map_style.h"
+#include "map_math.h"
#include "locationset.h"
#include "location.h"
#include "scenemanager.h"
@@ -51,6 +52,13 @@ static void map_draw_gdk_layer_fill(map_t* pMap, GdkPixmap* pPixmap, rendermetri
static void map_draw_gdk_locations(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics);
static void map_draw_gdk_locationset(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics, locationset_t* pLocationSet, GPtrArray* pLocationsArray);
+typedef struct {
+ GdkPixmap* pPixmap;
+ GdkGC* pGC;
+ maplayerstyle_t* pLayerStyle;
+ rendermetrics_t* pRenderMetrics;
+} gdk_draw_context_t;
+
//static void map_draw_gdk_tracks(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics);
void map_draw_gdk_set_color(GdkGC* pGC, color_t* pColor)
@@ -147,6 +155,53 @@ void map_draw_gdk(map_t* pMap, GPtrArray* pTiles, rendermetrics_t* pRenderMetric
TIMER_END(maptimer, "END RENDER MAP (gdk)");
}
+// useful for filling the screen with a color. not much else.
+static void map_draw_gdk_layer_fill(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics, maplayerstyle_t* pLayerStyle)
+{
+ GdkGC* pGC = pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)];
+
+ GdkGCValues gcValues;
+ if(pLayerStyle->pGlyphFill != NULL) {
+ // Instead of filling with a color, fill with a tiled image
+ gdk_gc_get_values(pGC, &gcValues);
+ gdk_gc_set_fill(pGC, GDK_TILED);
+ gdk_gc_set_tile(pGC, glyph_get_pixmap(pLayerStyle->pGlyphFill, pMap->pTargetWidget));
+
+ // This makes the fill image scroll with the map, instead of staying still
+ gdk_gc_set_ts_origin(pGC, SCALE_X(pRenderMetrics, pRenderMetrics->fScreenLongitude), SCALE_Y(pRenderMetrics, pRenderMetrics->fScreenLatitude));
+ }
+ else {
+ // Simple color fill
+ map_draw_gdk_set_color(pGC, &(pLayerStyle->clrPrimary));
+ }
+
+ gdk_draw_rectangle(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)],
+ TRUE, 0,0, pMap->MapDimensions.uWidth, pMap->MapDimensions.uHeight);
+
+ if(pLayerStyle->pGlyphFill != NULL) {
+ // Restore fill style
+ gdk_gc_set_values(pGC, &gcValues, GDK_GC_FILL);
+ }
+}
+
+//
+static void map_draw_gdk_polygons(const GArray* pMapPointsArray, const gdk_draw_context_t* pContext)
+{
+ // Copy all points into this array. Yuuup this is slow. :)
+ GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
+ mappoint_t* pPoint;
+
+ gint iPoint;
+ for(iPoint=0 ; iPoint<pMapPointsArray->len ; iPoint++) {
+ pPoint = &g_array_index(pMapPointsArray, mappoint_t, iPoint);
+
+ aPoints[iPoint].x = pContext->pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pContext->pRenderMetrics, pPoint->fLongitude);
+ aPoints[iPoint].y = pContext->pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pContext->pRenderMetrics, pPoint->fLatitude);
+ }
+
+ gdk_draw_polygon(pContext->pPixmap, pContext->pGC, TRUE, aPoints, pMapPointsArray->len);
+}
+
static void map_draw_gdk_layer_polygons(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics, GPtrArray* pRoadsArray, maplayerstyle_t* pLayerStyle)
{
mappoint_t* pPoint;
@@ -174,13 +229,21 @@ static void map_draw_gdk_layer_polygons(map_t* pMap, GdkPixmap* pPixmap, renderm
map_draw_gdk_set_color(pGC, &(pLayerStyle->clrPrimary));
}
+ gdk_draw_context_t context;
+ context.pPixmap = pPixmap;
+ context.pGC = pGC;
+ context.pLayerStyle = pLayerStyle;
+ context.pRenderMetrics = pRenderMetrics;
+
for(iString=0 ; iString<pRoadsArray->len ; iString++) {
pRoad = g_ptr_array_index(pRoadsArray, iString);
- if(!map_rects_overlap(&(pRoad->rWorldBoundingBox), &(pRenderMetrics->rWorldBoundingBox))) {
+ EOverlapType eOverlapType = map_rect_a_overlap_type_with_rect_b(&(pRoad->rWorldBoundingBox), &(pRenderMetrics->rWorldBoundingBox));
+ if(eOverlapType == OVERLAP_NONE) {
continue;
}
+ // XXX: should we remove this?
if(pRoad->pMapPointsArray->len < 3) {
//g_warning("not drawing polygon with < 3 points\n");
continue;
@@ -191,17 +254,15 @@ static void map_draw_gdk_layer_polygons(map_t* pMap, GdkPixmap* pPixmap, renderm
continue;
}
- GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
-
- for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
- pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
-
- aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
- aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
+ if(eOverlapType == OVERLAP_PARTIAL) {
+ // draw clipped
+ // XXX: Currently no clipping, just draw normally
+ map_draw_gdk_polygons(pRoad->pMapPointsArray, &context);
+ }
+ else {
+ // draw normally
+ map_draw_gdk_polygons(pRoad->pMapPointsArray, &context);
}
-
- gdk_draw_polygon(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)],
- TRUE, aPoints, pRoad->pMapPointsArray->len);
}
if(pLayerStyle->pGlyphFill != NULL) {
// Restore fill style
@@ -209,45 +270,34 @@ static void map_draw_gdk_layer_polygons(map_t* pMap, GdkPixmap* pPixmap, renderm
}
}
-// useful for filling the screen with a color. not much else.
-static void map_draw_gdk_layer_fill(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics, maplayerstyle_t* pLayerStyle)
+static void map_draw_gdk_lines(const GArray* pMapPointsArray, const gdk_draw_context_t* pContext)
{
- GdkGC* pGC = pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)];
-
- GdkGCValues gcValues;
- if(pLayerStyle->pGlyphFill != NULL) {
- // Instead of filling with a color, fill with a tiled image
- gdk_gc_get_values(pGC, &gcValues);
- gdk_gc_set_fill(pGC, GDK_TILED);
- gdk_gc_set_tile(pGC, glyph_get_pixmap(pLayerStyle->pGlyphFill, pMap->pTargetWidget));
-
- // This makes the fill image scroll with the map, instead of staying still
- gdk_gc_set_ts_origin(pGC, SCALE_X(pRenderMetrics, pRenderMetrics->fScreenLongitude), SCALE_Y(pRenderMetrics, pRenderMetrics->fScreenLatitude));
- }
- else {
- // Simple color fill
- map_draw_gdk_set_color(pGC, &(pLayerStyle->clrPrimary));
- }
+ // Copy all points into this array. Yuuup this is slow. :)
+ GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
+ mappoint_t* pPoint;
- gdk_draw_rectangle(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)],
- TRUE, 0,0, pMap->MapDimensions.uWidth, pMap->MapDimensions.uHeight);
+ gint iPoint;
+ for(iPoint=0 ; iPoint<pMapPointsArray->len ; iPoint++) {
+ pPoint = &g_array_index(pMapPointsArray, mappoint_t, iPoint);
- if(pLayerStyle->pGlyphFill != NULL) {
- // Restore fill style
- gdk_gc_set_values(pGC, &gcValues, GDK_GC_FILL);
+ aPoints[iPoint].x = pContext->pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pContext->pRenderMetrics, pPoint->fLongitude);
+ aPoints[iPoint].y = pContext->pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pContext->pRenderMetrics, pPoint->fLatitude);
}
+
+ gdk_draw_lines(pContext->pPixmap, pContext->pGC, aPoints, pMapPointsArray->len);
}
static void map_draw_gdk_layer_lines(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics, GPtrArray* pRoadsArray, maplayerstyle_t* pLayerStyle)
{
road_t* pRoad;
- mappoint_t* pPoint;
gint iString;
gint iPoint;
if(pLayerStyle->fLineWidth <= 0.0) return; // Don't draw invisible lines
if(pLayerStyle->clrPrimary.fAlpha == 0.0) return; // invisible? (not that we respect it in gdk drawing anyway)
+ GdkGC* pGC = pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)];
+
// Translate generic cap style into GDK constant
gint nCapStyle;
if(pLayerStyle->nCapStyle == MAP_CAP_STYLE_ROUND) {
@@ -278,10 +328,17 @@ static void map_draw_gdk_layer_lines(map_t* pMap, GdkPixmap* pPixmap, rendermetr
map_draw_gdk_set_color(pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)], &(pLayerStyle->clrPrimary));
+ gdk_draw_context_t context;
+ context.pPixmap = pPixmap;
+ context.pGC = pGC;
+ context.pLayerStyle = pLayerStyle;
+ context.pRenderMetrics = pRenderMetrics;
+
for(iString=0 ; iString<pRoadsArray->len ; iString++) {
pRoad = g_ptr_array_index(pRoadsArray, iString);
- if(!map_rects_overlap(&(pRoad->rWorldBoundingBox), &(pRenderMetrics->rWorldBoundingBox))) {
+ EOverlapType eOverlapType = map_rect_a_overlap_type_with_rect_b(&(pRoad->rWorldBoundingBox), &(pRenderMetrics->rWorldBoundingBox));
+ if(eOverlapType == OVERLAP_NONE) {
continue;
}
@@ -295,17 +352,14 @@ static void map_draw_gdk_layer_lines(map_t* pMap, GdkPixmap* pPixmap, rendermetr
continue;
}
- // Copy all points into this array. Yuuup this is slow. :)
- GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
-
- for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
- pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
-
- aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
- aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
+ if(eOverlapType == OVERLAP_PARTIAL) {
+ // draw clipped
+ map_draw_gdk_lines(pRoad->pMapPointsArray, &context);
+ }
+ else {
+ // draw directly
+ map_draw_gdk_lines(pRoad->pMapPointsArray, &context);
}
-
- gdk_draw_lines(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)], aPoints, pRoad->pMapPointsArray->len);
}
}
diff --git a/src/map_hittest.c b/src/map_hittest.c
index 6b7ac6d..9ab938d 100644
--- a/src/map_hittest.c
+++ b/src/map_hittest.c
@@ -333,7 +333,7 @@ static gboolean map_hittest_locationselections(map_t* pMap, rendermetrics_t* pRe
return FALSE;
}
-// Does the given point come close enough to the line segment to be considered a hit?
+
static gboolean map_hittest_line(mappoint_t* pPoint1, mappoint_t* pPoint2, mappoint_t* pHitPoint, gdouble fMaxDistance, mappoint_t* pReturnClosestPoint, gdouble* pfReturnPercentAlongLine)
{
if(pHitPoint->fLatitude < (pPoint1->fLatitude - fMaxDistance) && pHitPoint->fLatitude < (pPoint2->fLatitude - fMaxDistance)) return FALSE;
diff --git a/src/map_math.c b/src/map_math.c
index 6d820ff..3d63b80 100644
--- a/src/map_math.c
+++ b/src/map_math.c
@@ -23,6 +23,7 @@
#include <gtk/gtk.h>
#include "map.h"
+#include "map_math.h"
// ========================================================
// Coordinate Conversion Functions
@@ -65,6 +66,20 @@ void map_windowpoint_to_mappoint(map_t* pMap, screenpoint_t* pScreenPoint, mappo
pMapPoint->fLatitude = pMap->MapCenter.fLatitude - map_pixels_to_degrees(pMap, nPixelDeltaY, pMap->uZoomLevel);
}
+EOverlapType map_rect_a_overlap_type_with_rect_b(const maprect_t* pA, const maprect_t* pB)
+{
+ // First, quickly determine if there is no overlap
+ if(map_rects_overlap(pA,pB) == FALSE) return OVERLAP_NONE;
+
+ if(pA->A.fLatitude < pB->A.fLatitude) return OVERLAP_PARTIAL;
+ if(pA->B.fLatitude > pB->B.fLatitude) return OVERLAP_PARTIAL;
+
+ if(pA->A.fLongitude < pB->A.fLongitude) return OVERLAP_PARTIAL;
+ if(pA->B.fLongitude > pB->B.fLongitude) return OVERLAP_PARTIAL;
+
+ return OVERLAP_FULL;
+}
+
gboolean map_rects_overlap(const maprect_t* p1, const maprect_t* p2)
{
if(p1->B.fLatitude < p2->A.fLatitude) return FALSE;
@@ -159,6 +174,169 @@ gboolean map_math_maprects_equal(maprect_t* pA, maprect_t* pB)
return map_points_equal(&(pA->A), &(pB->A)) && map_points_equal(&(pA->B), &(pB->B));
}
+//
+// clipping a map polygon (array of mappoints) to a maprect
+//
+typedef enum { EDGE_NORTH, EDGE_SOUTH, EDGE_EAST, EDGE_WEST, EDGE_FIRST=0, EDGE_LAST=3 } ERectEdge;
+
+// static map_math_clip_line_to_worldrect_edge_recursive(mappoint_t* pA, mappoint_t* pB, maprect_t* pRect, ERectEdge eEdge, GArray* pOutput)
+// {
+//
+// }
+
+gboolean map_math_mappoint_in_maprect(const mappoint_t* pPoint, const maprect_t* pRect)
+{
+ if(pPoint->fLatitude < pRect->A.fLatitude) return FALSE;
+ if(pPoint->fLatitude > pRect->B.fLatitude) return FALSE;
+ if(pPoint->fLongitude < pRect->A.fLongitude) return FALSE;
+ if(pPoint->fLongitude > pRect->B.fLongitude) return FALSE;
+ return TRUE;
+}
+
+void map_math_clip_pointstring_to_worldrect(GArray* pMapPointsArray, maprect_t* pRect, GArray* pOutput)
+{
+ gint nLen = pMapPointsArray->len;
+ if(nLen <= 2) return;
+
+ mappoint_t* pA = &g_array_index(pMapPointsArray, mappoint_t, 0);
+ mappoint_t* pB = NULL;
+
+ gboolean bPointAIsInside = map_math_mappoint_in_maprect(pA, pRect);
+
+ gint i;
+ for(i=1 ; i<pMapPointsArray->len ; i++) {
+ gint iEdge;
+ for(iEdge=EDGE_FIRST ; iEdge<=EDGE_LAST ; iEdge++) {
+ switch(iEdge) {
+ case EDGE_NORTH:
+ break;
+ case EDGE_SOUTH:
+ break;
+ case EDGE_EAST:
+ break;
+ case EDGE_WEST:
+ break;
+ }
+ }
+ }
+}
+
+void static map_math_simplify_pointstring_recursive(const GArray* pInput, gint8* pabInclude, gdouble fTolerance, gint iFirst, gint iLast)
+{
+ if(iFirst+1 >= iLast) return; // no points between first and last?
+
+ mappoint_t* pA = &g_array_index(pInput, mappoint_t, iFirst);
+ mappoint_t* pB = &g_array_index(pInput, mappoint_t, iLast);
+
+ // Init to bad values
+ gint iFarthestIndex = -1;
+ gdouble fBiggestDistanceSquared = 0.0;
+
+ // Of all points between A and B, which is farthest from the line AB?
+ mappoint_t* pPoint;
+ gint i;
+ for(i=(iFirst+1) ; i<=(iLast-1) ; i++) {
+ pPoint = &g_array_index(pInput, mappoint_t, i);
+ gdouble fDistanceSquared = map_math_point_distance_squared_from_line(pPoint, pA, pB);
+
+ if(fDistanceSquared > fBiggestDistanceSquared) {
+ fBiggestDistanceSquared = fDistanceSquared;
+ iFarthestIndex = i;
+ }
+ }
+ if(fBiggestDistanceSquared > (fTolerance * fTolerance) && (iFarthestIndex != -1)) { // add last test just in case fTolerance == 0.0
+ // Mark for inclusion
+ pabInclude[iFarthestIndex] = 1;
+
+ map_math_simplify_pointstring_recursive(pInput, pabInclude, fTolerance, iFirst, iFarthestIndex);
+ map_math_simplify_pointstring_recursive(pInput, pabInclude, fTolerance, iFarthestIndex, iLast);
+ }
+}
+
+void map_math_simplify_pointstring(const GArray* pInput, gdouble fTolerance, GArray* pOutput)
+{
+ if(pInput->len < 2) return;
+
+ gint8* pabInclude = g_new0(gint8, pInput->len + 20);
+
+ // Mark first and last points
+ pabInclude[0] = 1;
+ pabInclude[pInput->len-1] = 1;
+
+ map_math_simplify_pointstring_recursive(pInput, pabInclude, fTolerance, 0, pInput->len-1);
+
+ //
+ // cleanup
+ //
+ mappoint_t* pPoint;
+ gint i;
+ for(i=0 ; i<pInput->len ; i++) {
+ pPoint = &g_array_index(pInput, mappoint_t, i);
+ if(pabInclude[i] == 1) {
+ g_array_append_val(pOutput, *pPoint);
+ }
+ }
+ g_free(pabInclude);
+}
+
+// Does the given point come close enough to the line segment to be considered a hit?
+gdouble map_math_point_distance_squared_from_line(mappoint_t* pHitPoint, mappoint_t* pPoint1, mappoint_t* pPoint2)
+{
+ // Some bad ASCII art demonstrating the situation:
+ //
+ // / (u)
+ // / |
+ // / |
+ // (0,0) =====(a)========== (v)
+
+ // v is the translated-to-origin vector of line
+ // u is the translated-to-origin vector of the hitpoint
+ // a is the closest point on v to the end of u (the hit point)
+
+ //
+ // 1. Convert p1->p2 vector into a vector (v) that is assumed to come out of the origin (0,0)
+ //
+ mappoint_t v;
+ v.fLatitude = pPoint2->fLatitude - pPoint1->fLatitude; // 10->90 becomes 0->80 (just store 80)
+ v.fLongitude = pPoint2->fLongitude - pPoint1->fLongitude;
+
+ gdouble fLengthV = sqrt((v.fLatitude*v.fLatitude) + (v.fLongitude*v.fLongitude));
+ if(fLengthV == 0.0) return FALSE; // bad data: a line segment with no length?
+
+ //
+ // 2. Make a unit vector out of v (meaning same direction but length=1) by dividing v by v's length
+ //
+ mappoint_t unitv;
+ unitv.fLatitude = v.fLatitude / fLengthV;
+ unitv.fLongitude = v.fLongitude / fLengthV; // unitv is now a unit (=1.0) length v
+
+ //
+ // 3. Translate the hitpoint in the same way we translated v
+ //
+ mappoint_t u;
+ u.fLatitude = pHitPoint->fLatitude - pPoint1->fLatitude;
+ u.fLongitude = pHitPoint->fLongitude - pPoint1->fLongitude;
+
+ //
+ // 4. Use the dot product of (unitv) and (u) to find (a), the point along (v) that is closest to (u). see diagram above.
+ //
+ gdouble fLengthAlongV = (unitv.fLatitude * u.fLatitude) + (unitv.fLongitude * u.fLongitude);
+
+ mappoint_t a;
+ a.fLatitude = v.fLatitude * (fLengthAlongV / fLengthV); // multiply each component by the percentage
+ a.fLongitude = v.fLongitude * (fLengthAlongV / fLengthV);
+ // NOTE: (a) is *not* where it actually hit on the *map*. don't draw this point! we'd have to translate it back away from the origin.
+
+ //
+ // 5. Calculate the distance from the end of (u) to (a). If it's less than the fMaxDistance, it's a hit.
+ //
+ gdouble fRise = u.fLatitude - a.fLatitude;
+ gdouble fRun = u.fLongitude - a.fLongitude;
+ gdouble fDistanceSquared = fRise*fRise + fRun*fRun; // compare squared distances. same results but without the sqrt.
+
+ return fDistanceSquared;
+}
+
#ifdef ROADSTER_DEAD_CODE
/*
diff --git a/src/map_math.h b/src/map_math.h
index 5643b98..b7c6c99 100644
--- a/src/map_math.h
+++ b/src/map_math.h
@@ -24,7 +24,19 @@
#ifndef _MAP_MATH_H_
#define _MAP_MATH_H_
+typedef enum {
+ OVERLAP_FULL,
+ OVERLAP_NONE,
+ OVERLAP_PARTIAL
+} EOverlapType;
+
gboolean map_math_screenpoint_in_screenrect(screenpoint_t* pPt, screenrect_t* pRect);
gboolean map_math_maprects_equal(maprect_t* pA, maprect_t* pB);
+EOverlapType map_rect_a_overlap_type_with_rect_b(const maprect_t* pA, const maprect_t* pB);
+gboolean map_rects_overlap(const maprect_t* p1, const maprect_t* p2);
+
+void map_math_simplify_pointstring(const GArray* pInput, gdouble fTolerance, GArray* pOutput);
+gdouble map_math_point_distance_squared_from_line(mappoint_t* pHitPoint, mappoint_t* pPoint1, mappoint_t* pPoint2);
+
#endif
diff --git a/src/test_poly.c b/src/test_poly.c
new file mode 100644
index 0000000..6208806
--- /dev/null
+++ b/src/test_poly.c
@@ -0,0 +1,209 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
+
+#include "gui.h"
+#include "map.h"
+#include "util.h"
+
+struct {
+ GtkWindow* pWindow;
+
+ GtkHScale* pScale;
+ GtkVBox* pContentBox;
+ GtkButton* pClearButton;
+ GtkDrawingArea* pDrawingArea;
+ GtkLabel* pLabel;
+
+ GArray* pPointsArray;
+} g_Test_Poly;
+
+static gboolean on_time_to_update(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data);
+static void test_poly_draw();
+static gboolean on_mouse_button_click(GtkWidget* w, GdkEventButton *event);
+static gboolean on_clear_clicked(GtkWidget* w, GdkEventButton *event);
+
+void test_poly_init(GladeXML* pGladeXML)
+{
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pWindow, GTK_WINDOW, "test_polywindow");
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pScale, GTK_HSCALE, "test_poly_scale");
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pContentBox, GTK_VBOX, "test_poly_contentbox");
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pClearButton, GTK_BUTTON, "test_poly_clear_button");
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pLabel, GTK_LABEL, "test_polylabel");
+ GLADE_LINK_WIDGET(pGladeXML, g_Test_Poly.pDrawingArea, GTK_DRAWING_AREA, "test_polydrawingarea");
+
+ g_Test_Poly.pPointsArray = g_array_new(FALSE, FALSE, sizeof(mappoint_t));
+
+ // Drawing area
+ gtk_widget_set_double_buffered(GTK_WIDGET(g_Test_Poly.pDrawingArea), FALSE);
+ gtk_widget_add_events(GTK_WIDGET(g_Test_Poly.pDrawingArea), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
+ g_signal_connect(G_OBJECT(g_Test_Poly.pDrawingArea), "expose-event", G_CALLBACK(on_time_to_update), NULL);
+ g_signal_connect(G_OBJECT(g_Test_Poly.pDrawingArea), "button_press_event", G_CALLBACK(on_mouse_button_click), NULL);
+
+ // Scale
+ g_signal_connect(G_OBJECT(g_Test_Poly.pScale), "value-changed", G_CALLBACK(on_time_to_update), NULL);
+ // make it instant-change using our hacky callback
+ //g_signal_connect(G_OBJECT(g_Test_Poly.pScale), "change-value", G_CALLBACK(util_gtk_range_instant_set_on_value_changing_callback), NULL);
+
+ // "Clear" button
+ g_signal_connect(G_OBJECT(g_Test_Poly.pClearButton), "clicked", G_CALLBACK(on_clear_clicked), NULL);
+
+ // don't delete window on X, just hide it
+ g_signal_connect(G_OBJECT(g_Test_Poly.pWindow), "delete_event", G_CALLBACK(gtk_widget_hide), NULL);
+}
+
+void test_poly_show(GtkMenuItem *menuitem, gpointer user_data)
+{
+ gtk_widget_show(GTK_WIDGET(g_Test_Poly.pWindow));
+}
+
+static gboolean on_clear_clicked(GtkWidget* w, GdkEventButton *event)
+{
+ g_array_remove_range(g_Test_Poly.pPointsArray, 0, g_Test_Poly.pPointsArray->len);
+ gtk_widget_queue_draw(GTK_WIDGET(g_Test_Poly.pDrawingArea));
+}
+
+static gboolean on_mouse_button_click(GtkWidget* w, GdkEventButton *event)
+{
+ gint nX, nY;
+ gdk_window_get_pointer(w->window, &nX, &nY, NULL);
+
+ gint nWidth = GTK_WIDGET(g_Test_Poly.pDrawingArea)->allocation.width;
+ gint nHeight = GTK_WIDGET(g_Test_Poly.pDrawingArea)->allocation.height;
+
+ mappoint_t point;
+ point.fLongitude = (gdouble)nX / (gdouble)nWidth;
+ point.fLatitude = (gdouble)nY / (gdouble)nHeight;
+ g_array_append_val(g_Test_Poly.pPointsArray, point);
+
+ gtk_widget_queue_draw(GTK_WIDGET(g_Test_Poly.pDrawingArea));
+}
+
+void test_poly_draw_array(cairo_t* pCairo, GArray* pArray)
+{
+ if(pArray->len >= 1) {
+ mappoint_t* pPoint;
+ pPoint = &g_array_index(pArray, mappoint_t, 0);
+ cairo_move_to(pCairo, pPoint->fLongitude, pPoint->fLatitude);
+ cairo_arc(pCairo, pPoint->fLongitude, pPoint->fLatitude, 0.02, 0, 2*M_PI);
+ cairo_fill(pCairo);
+ cairo_move_to(pCairo, pPoint->fLongitude, pPoint->fLatitude);
+ gint i;
+ for(i=1 ; i<pArray->len ;i++) {
+ pPoint = &g_array_index(pArray, mappoint_t, i);
+ cairo_line_to(pCairo, pPoint->fLongitude, pPoint->fLatitude);
+ }
+ pPoint = &g_array_index(pArray, mappoint_t, 0);
+ cairo_line_to(pCairo, pPoint->fLongitude, pPoint->fLatitude);
+ }
+}
+
+static gboolean on_time_to_update(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data)
+{
+ Display* dpy;
+ Drawable drawable;
+ dpy = gdk_x11_drawable_get_xdisplay(GTK_WIDGET(g_Test_Poly.pDrawingArea)->window);
+ Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
+ gint width, height;
+ drawable = gdk_x11_drawable_get_xid(GTK_WIDGET(g_Test_Poly.pDrawingArea)->window);
+ gdk_drawable_get_size (GTK_WIDGET(g_Test_Poly.pDrawingArea)->window, &width, &height);
+ cairo_surface_t *pSurface = cairo_xlib_surface_create (dpy, drawable, visual, width, height);
+
+ gdouble fValue = gtk_range_get_value(g_Test_Poly.pScale);
+
+ cairo_t* pCairo = cairo_create (pSurface);
+
+ cairo_scale(pCairo, width, height);
+
+ cairo_set_source_rgba(pCairo, 1.0, 1.0, 1.0, 1.0);
+ cairo_rectangle(pCairo, 0.0, 0.0, 1.0, 1.0);
+ cairo_fill(pCairo);
+
+ // Draw lines
+ cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_ROUND);
+ cairo_save(pCairo);
+ cairo_set_line_width(pCairo, 0.02);
+ cairo_set_source_rgba(pCairo, 1.0, 0.0, 0.0, 1.0);
+ test_poly_draw_array(pCairo, g_Test_Poly.pPointsArray);
+ cairo_stroke(pCairo);
+ cairo_restore(pCairo);
+
+ cairo_save(pCairo);
+ GArray* pSimplified = g_array_new(FALSE, FALSE, sizeof(mappoint_t));
+ map_math_simplify_pointstring(g_Test_Poly.pPointsArray, fValue, pSimplified);
+ cairo_set_line_width(pCairo, 0.01);
+ cairo_set_source_rgba(pCairo, 0.0, 1.0, 0.0, 0.5);
+ test_poly_draw_array(pCairo, pSimplified);
+ cairo_fill(pCairo);
+ cairo_restore(pCairo);
+
+ cairo_destroy(pCairo);
+
+ if(g_Test_Poly.pPointsArray->len == 0) {
+ gtk_label_set_markup(g_Test_Poly.pLabel, "<b>Click to create points</b>");
+ }
+ else {
+ gchar* pszMarkup = g_strdup_printf("%d points, %d simplified", g_Test_Poly.pPointsArray->len, pSimplified->len);
+ gtk_label_set_markup(g_Test_Poly.pLabel, pszMarkup);
+ g_free(pszMarkup);
+ }
+
+ g_array_free(pSimplified, TRUE);
+ return TRUE;
+}
+
+// static void paint (GtkWidget *widget,GdkEventExpose *eev,gpointer data)
+// {
+// gint width, height;
+// gint i;
+// cairo_t *cr;
+//
+// width = widget->allocation.width;
+// height = widget->allocation.height;
+//
+// cr = gdk_cairo_create (widget->window);
+//
+// /* clear background */
+// cairo_set_source_rgb (cr, 1,1,1);
+// cairo_paint (cr);
+//
+//
+// cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
+// CAIRO_FONT_WEIGHT_BOLD);
+//
+// /* enclosing in a save/restore pair since we alter the
+// * font size
+// */
+// cairo_save (cr);
+// cairo_set_font_size (cr, 40);
+// cairo_move_to (cr, 40, 60);
+// cairo_set_source_rgb (cr, 0,0,0);
+// cairo_show_text (cr, "Hello World");
+// cairo_restore (cr);
+//
+// cairo_set_source_rgb (cr, 1,0,0);
+// cairo_set_font_size (cr, 20);
+// cairo_move_to (cr, 50, 100);
+// cairo_show_text (cr, "greetings from gtk and cairo");
+//
+// cairo_set_source_rgb (cr, 0,0,1);
+//
+// cairo_move_to (cr, 0, 150);
+// for (i=0; i< width/10; i++)
+// {
+// cairo_rel_line_to (cr, 5, 10);
+// cairo_rel_line_to (cr, 5, -10);
+// }
+// cairo_stroke (cr);
+//
+// cairo_destroy (cr);
+// }
+//
+// static gboolean on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data)
+// {
+// }
diff --git a/src/test_poly.h b/src/test_poly.h
new file mode 100644
index 0000000..c0476f6
--- /dev/null
+++ b/src/test_poly.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * test_poly.h
+ *
+ * Copyright 2005 Ian McIntosh
+ * ian_mcintosh@linuxadvocate.org
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TEST_POLY_H_
+#define _TEST_POLY_H_
+
+#include <glade/glade.h>
+
+void test_poly_init(GladeXML* pGladeXML);
+
+#endif