3 * Copyright (c) 2008 Paolo Molaro lupus@oddwiz.org
4 * License: MIT/X11, see the MIT.X11 file.
11 using System
.Collections
;
12 using System
.Collections
.Generic
;
22 static void Usage_r (int retval
)
24 Console
.WriteLine ("Usage:");
25 Console
.WriteLine ("\tosm-history node|way|relation id");
26 Console
.WriteLine ("\tosm-history --help");
27 Environment
.Exit (retval
);
30 static string[] GetTags (OsmObject obj
)
32 ICollection tags
= obj
.Tags
;
33 string[] arr
= new string [tags
.Count
];
39 static void CompareTags (OsmObject a
, OsmObject b
)
41 string[] ta
= GetTags (a
);
42 string[] tb
= GetTags (b
);
45 for (; i
< ta
.Length
&& j
< tb
.Length
; i
++, j
++) {
47 int cmp
= string.Compare (tag
, tb
[j
], StringComparison
.Ordinal
);
49 if (a
[tag
] != b
[tag
])
50 Console
.WriteLine ("\tTag {0}: {1} -> {2}", tag
, a
[tag
], b
[tag
]);
54 Console
.WriteLine ("\tTag removed: {0} (was: {1})", tag
, a
[tag
]);
57 Console
.WriteLine ("\tTag added: {0}: {1}", tb
[j
], b
[tb
[j
]]);
61 while (i
< ta
.Length
) {
62 Console
.WriteLine ("\tTag removed: {0} (was: {1})", ta
[i
], a
[ta
[i
]]);
65 while (j
< tb
.Length
) {
66 Console
.WriteLine ("\tTag added: {0}: {1}", tb
[j
], b
[tb
[j
]]);
71 static void CompareNodes (Node a
, Node b
)
73 if (a
.Latitude
!= b
.Latitude
)
74 Console
.WriteLine ("\tLatitude {0} -> {1}", a
.Latitude
, b
.Latitude
);
75 if (a
.Longitude
!= b
.Longitude
)
76 Console
.WriteLine ("\tLongitude {0} -> {1}", a
.Longitude
, b
.Longitude
);
83 // node node 253003550
84 // Not the most compact diff output, but good enough for most osm cases
85 static void DiffNodes (long[] an
, long[] bn
) {
90 StringBuilder sb
= new StringBuilder ();
91 for (; pos
< an
.Length
; ++pos
, ++adj_pos
) {
92 int mpos
= Array
.IndexOf (bn
, an
[pos
], bpos
);
93 if (mpos
== adj_pos
) {
98 if (index_out
!= adj_pos
- 1) {
99 sb
.AppendFormat (" {0}:", adj_pos
);
102 sb
.AppendFormat (" -{0}", an
[pos
]);
105 for (; bpos
< mpos
; bpos
++) {
106 if (index_out
!= adj_pos
- 1) {
107 sb
.AppendFormat (" {0}:", adj_pos
);
110 sb
.AppendFormat (" +{0}", bn
[bpos
]);
114 for (; bpos
< bn
.Length
; bpos
++) {
115 if (index_out
!= adj_pos
- 1) {
116 sb
.AppendFormat (" {0}:", adj_pos
);
119 sb
.AppendFormat (" +{0}", bn
[bpos
]);
122 Console
.WriteLine ("\tNodes:{0}", sb
.ToString ());
123 //Console.WriteLine ("Nodes: {0}", bn.Length);
127 static void CompareWays (Way a
, Way b
)
131 // simple check for a reverse
132 if (an
.Length
== bn
.Length
&& an
.Length
> 0) {
133 if (an
[0] != bn
[0] && an
[0] == bn
[bn
.Length
- 1]) {
135 for (int i
= 0; i
< an
.Length
; ++i
) {
136 if (an
[i
] != bn
[bn
.Length
- i
- 1]) {
142 Console
.WriteLine ("\tNodes reversed.");
148 // we don't check the nodes coordinates: it would likely be too expensive
151 static int CompareMember (RelationMember ma
, RelationMember mb
) {
152 int cmp
= string.Compare (ma
.Type
, mb
.Type
, StringComparison
.Ordinal
);
155 long diff
= ma
.Ref
- mb
.Ref
;
160 return string.Compare (ma
.Role
, mb
.Role
, StringComparison
.Ordinal
);
163 static RelationMember
[] GetMembers (Relation obj
)
165 RelationMember
[] members
= obj
.Members
;
166 if (members
.Length
<= 1)
168 members
= members
.Clone () as RelationMember
[];
169 Array
.Sort (members
, CompareMember
);
173 static string MemberDesc (RelationMember m
) {
174 return string.Format ("type={0} ref={1} role={2}", m
.Type
, m
.Ref
, m
.Role
);
177 static void CompareRelations (Relation a
, Relation b
)
179 RelationMember
[] ta
= GetMembers (a
);
180 RelationMember
[] tb
= GetMembers (b
);
183 for (; i
< ta
.Length
&& j
< tb
.Length
; i
++, j
++) {
184 int cmp
= CompareMember (ta
[i
], tb
[j
]);
188 Console
.WriteLine ("\tMember removed: {0}", MemberDesc (ta
[i
]));
191 Console
.WriteLine ("\tMember added: {0}", MemberDesc (tb
[j
]));
195 while (i
< ta
.Length
) {
196 Console
.WriteLine ("\tMember removed: {0}", MemberDesc (ta
[i
]));
199 while (j
< tb
.Length
) {
200 Console
.WriteLine ("\tMember added: {0}", MemberDesc (tb
[j
]));
205 static void PrintDiff (OsmObject a
, OsmObject b
)
207 // FIXME: make it clear when a way/node is removed
208 if (a
.Visible
!= b
.Visible
)
209 Console
.WriteLine ("\tVisible = {0}", b
.Visible
);
212 CompareNodes (a
as Node
, b
as Node
);
214 CompareWays (a
as Way
, b
as Way
);
216 CompareRelations (a
as Relation
, b
as Relation
);
219 static int Main (string[] args
)
224 //bool out_data = false;
226 if (args
.Length
> 0 && args
[0] == "--help") {
229 if (args
.Length
> 0 && args
[0] == "--out") {
233 if (args
.Length
- i
!= 2)
236 if (type
!= "node" && type
!= "way" && type
!= "relation")
239 id
= long.Parse (args
[i
+ 1]);
244 DataBase db
= new DataBase ();
245 IEnumerable
<OsmObject
> list
;
247 list
= db
.LoadHistory (type
, id
);
248 } catch (Exception e
) {
249 Console
.WriteLine (e
.Message
);
252 OsmObject last
= null;
254 foreach (OsmObject obj
in list
) {
255 Console
.WriteLine ("Version: {0} User: {1}, Time: {2}", v
, obj
.User
, obj
.TimeStamp
);
258 PrintDiff (last
, obj
);