/// <summary> /// Implements IComparer.Compare. Will compare either a WplIndexEntry or its numeric index (int) /// to a string (the name being searched for. /// </summary> /// <param name="x">The WplIndexEntry itself or its offset as an int</param> /// <param name="y">The name bein searched for as string</param> /// <returns></returns> public int Compare(object x, object y) { WplIndexEntry ie; // support comparing of index index or index entries directly if (x.GetType() == typeof(int)) { // a numeric index was provided, retrieve corresponding entry ie = myWplIndex.m_indexEntries[(int)x]; } else { // we got an entry, just cast ie = (WplIndexEntry)x; } // Read place item, omitting metadata as we're interested in the name only PlaceItem pi = myWplIndex.GetPlaceItemFromIndexEntry(ie, MetaDataAction.Omit); if (!partialAllowed) { return(String.Compare(pi.pn.Name, (string)y, true)); } string strSearch = (string)y; return(String.Compare(pi.pn.Name, 0, strSearch, 0, strSearch.Length, true)); }
/// <summary> /// Fills a PlaceListSettings class (used to serialize places) with all the places in the list /// </summary> /// <param name="pls">The PlaceListSettings class that will receive the places</param> public void FillSettingsFromList(PlaceListSettings pls) { pls.places = new PlaceListSettings.PlaceData [this.Items.Count]; for (int i = 0; i < this.Items.Count; i++) { PlaceItem pi = (PlaceItem)this.Items[i].Tag; PlaceListSettings.PlaceData pd = new PlaceListSettings.PlaceData(); pd.Name = pi.pn.Name; pd.Lat = pi.pn.Lat; pd.Lon = pi.pn.Lon; int mdCount = pi.pn.metaData == null ? 0 : pi.pn.metaData.Count; pd.metadata = new PlaceListSettings.MetaDataEntry [mdCount]; int j = 0; if (pi.pn.metaData != null) { foreach (DictionaryEntry de in pi.pn.metaData) { pd.metadata[j] = new PlaceListSettings.MetaDataEntry(); pd.metadata[j].name = de.Key.ToString(); pd.metadata[j].value = de.Value.ToString(); j++; } } pls.places[i] = pd; } }
/// <summary> /// Saves places to a file in GPX format, given pathname /// </summary> /// <param name="strGpxPath">The file (with full path) to save to</param> public void SaveToGpx(string strGpxPath) { gpxType gpx = new gpxType(); gpx.creator = "NASA World Wind"; gpx.version = "1.1"; gpx.wpt = new wptType [this.Items.Count]; int i = 0; foreach (ListViewItem lvi in this.Items) { PlaceItem pi = (PlaceItem)lvi.Tag; wptType wp = new wptType(); wp.name = pi.pn.Name; wp.lat = (decimal)pi.pn.Lat; wp.lon = (decimal)pi.pn.Lon; wp.sym = "Waypoint"; gpx.wpt[i++] = wp; } XmlSerializer ser = new XmlSerializer(typeof(gpxType)); TextWriter tw = new StreamWriter(strGpxPath); ser.Serialize(tw, gpx); tw.Close(); }
// perform a full search in a placename set, with attributes bool PlaceNameSetFullSearch(string [] searchTokens, IndexedTiledPlaceNameSet curIndexedTiledSet) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName( Path.Combine( Path.GetDirectoryName(Application.ExecutablePath), curIndexedTiledSet.placenameSet.PlacenameListFilePath.Value))); // ignore this set if the corresponding directory does not exist for some reason if (!dir.Exists) { return(true); } // loop over all WWP files in directory foreach (FileInfo placenameFile in dir.GetFiles("*.wwp")) { using (BinaryReader reader = new BinaryReader(placenameFile.OpenRead())) { int placenameCount = reader.ReadInt32(); // loop over all places for (int i = 0; i < placenameCount; i++) { // return false if stop requested if (CheckStopRequested()) { return(false); } // instantiate and read current placename WorldWindPlacename pn = new WorldWindPlacename(); WplIndex.ReadPlaceName(reader, ref pn, WplIndex.MetaDataAction.Store); // if we have a match ... if (isPlaceMatched(searchTokens, pn)) { if (CheckMaxResults()) { return(false); } PlaceItem pi = new PlaceItem(); pi.pn = pn; pi.placeDescriptor = curIndexedTiledSet.placenameSet; // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); } } } } return(true); // go on }
// adds a place (given by index) found via binary search to the list, and adds places above and below it // in the sort order as long as they match bool AddIndexAndVicinity(int nPos, IndexedTiledPlaceNameSet itps, string strSearch, bool bPartialAllowed) { PlaceItem pi = itps.wplIndex.GetPlaceItem(nPos); // get the place from the index // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); // instantiate our special comparer - will compare search string to a place given by index - this is the same one // we're using in the binary search WplIndex.IndexEntryToStringComparer cmp = new WplIndex.IndexEntryToStringComparer(itps.wplIndex, bPartialAllowed); int nBelow = nPos - 1; // left neighbour in search order (if any) int nAbove = nPos + 1; // right neighbour in search order (if any) bool bFoundOne; // keeps track if "expansion mechanism" still found something do { // return false if stop requested or too many results if (CheckStopRequested() || CheckMaxResults()) { return(false); } bFoundOne = false; if (itps.wplIndex.IsValidIndex(nBelow) && cmp.Compare(nBelow, strSearch) == 0) { // left neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nBelow); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); --nBelow; // expand to the left bFoundOne = true; } if (itps.wplIndex.IsValidIndex(nAbove) && cmp.Compare(nAbove, strSearch) == 0) { // right neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nAbove); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); ++nAbove; // expand to the left bFoundOne = true; } } while(bFoundOne); // keep expanding until nothing new on both sides return(true); // keep searching }
// Someone clicked on a search result line void placelistView_SelectedIndexChanged(object sender, System.EventArgs e) { WWPlaceListView plw = (WWPlaceListView)sender; if (plw.SelectedItems.Count == 0 || // ignore if no entries in list .. plw.SelectedItems[0].Tag == null) { return; // ... or if selected entry has no attached placename info } PlaceItem pi = (PlaceItem)plw.SelectedItems[0].Tag; // retrieve info // set lat, lon and altitude this.numericUpDownLatitude.Value = (decimal)pi.pn.Lat; this.numericUpDownLongitude.Value = (decimal)pi.pn.Lon; this.numericUpDownAltitude.Value = (decimal)(pi.Altitude / 1000.0); // and go there. this.worldWindow.GotoLatLonViewRange(pi.pn.Lat, pi.pn.Lon, 90.0f); }
// add the places from a single wwp file to our places array // note that nNextEntry is passed by reference - the total count is accumulated here void AddSingleWwpPlaces(int nFileNbr, ref int nNextEntry) { // open reader using (BinaryReader brWwp = OpenWwpReader(nFileNbr)) { int nEntryCount = brWwp.ReadInt32(); // read number of entries for (int i = 0; i < nEntryCount; i++) { IndexedPlace ip = new IndexedPlace(); // allocate indexed place class to store entries ip.pn = new WorldWindPlacename(); ip.placeDescriptor = this.m_placeNameSet; // "inherit" placeNameSet ip.indexEntry.fileNumber = (System.Int16)nFileNbr; // remember file number ip.indexEntry.seekOffset = (int)brWwp.BaseStream.Position; // and location in file PlaceItem pi = ip; ReadPlaceName(brWwp, ref pi.pn, MetaDataAction.Skip); // skipping the metadata is faster this.m_indexedPlaces[nNextEntry++] = ip; // remember this indexed place } } }
// given an index descriptor, seek to and return place information PlaceItem GetPlaceItemFromIndexEntry(WplIndexEntry ie, MetaDataAction metaDataAction) { using (BinaryReader brWwp = OpenWwpReader(ie.fileNumber)) { // seek to the relevant info brWwp.BaseStream.Seek(ie.seekOffset, SeekOrigin.Begin); // create a new PlaceItem PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); // set placeNameSet info pi.placeDescriptor = this.m_placeNameSet; // now read the rest from the WWP file ReadPlaceName(brWwp, ref pi.pn, metaDataAction); return(pi); } }
/// <summary> /// A doubleclick goes to the corresponding place and /// also adds it to the history list /// </summary> /// <param name="e"></param> protected override void OnDoubleClick(EventArgs e) { base.OnDoubleClick(e); ListViewItem lvi = this.FocusedItem; if (lvi == null) { return; } PlaceItem pi = (PlaceItem)lvi.Tag; if (this.WorldWindow != null) { pi.Goto(this.m_worldWindow); } if (this.RecentFinds != null) { this.RecentFinds.AddPlace(pi); } }
/// <summary> /// Loads places from a file in GPX format, given pathname /// </summary> /// <param name="strGpxPath">The file (with full path) in GPX format to load from</param> public void LoadFromGpx(string strGpxPath) { if (!File.Exists(strGpxPath)) { return; } XmlSerializer ser = new XmlSerializer(typeof(gpxType)); TextReader tr = new StreamReader(strGpxPath); gpxType gpx = null; try { gpx = (gpxType)ser.Deserialize(tr); } catch (Exception caught) { // TODO: log error System.Diagnostics.Debug.WriteLine(caught.InnerException.ToString()); } tr.Close(); if (gpx == null || gpx.wpt == null) { return; } foreach (wptType wpt in gpx.wpt) { PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); pi.pn.Name = wpt.name; pi.pn.Lat = (float)wpt.lat; pi.pn.Lon = (float)wpt.lon; AddPlace(pi); } }
/// <summary> /// Fills the list with all the places in a PlaceListSettings class (used to serialize places) /// </summary> /// <param name="pls">The PlaceListSettings class that contains all the places</param> public void FillListFromSettings(PlaceListSettings pls) { // clear the list this.Items.Clear(); if (pls.places == null) { return; // nothing to do } foreach (PlaceListSettings.PlaceData pd in pls.places) { PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); pi.pn.Name = pd.Name; pi.pn.Lat = (float)pd.Lat; pi.pn.Lon = (float)pd.Lon; pi.pn.metaData = new Hashtable(); for (int i = 0; i < pd.metadata.Length; i++) { pi.pn.metaData.Add(pd.metadata[i].name, pd.metadata[i].value); } AddPlace(pi); } }
/// <summary> /// Adds a place given a PlaceItem /// </summary> /// <param name="pi">PlaceItem class describing the place</param> public void AddPlace(PlaceItem pi) { Hashtable knv = new Hashtable(); // holds name/value pairs // add the "standard" attributes to the hashtable knv.Add("Name", pi.pn.Name); // pi.strPlaceName); knv.Add("Layer", pi.placeDescriptor == null ? "" : pi.placeDescriptor.Name.Value); knv.Add("Latitude", pi.pn.Lat.ToString()); // pi.lat.ToString()); knv.Add("Longitude", pi.pn.Lon.ToString()); // pi.lon.ToString()); // now add metadata attributes if (pi.pn.metaData != null) { foreach (DictionaryEntry de in pi.pn.metaData) { knv.Add(de.Key, de.Value); } } // add to the list via the hashtable ListViewItem lvi = this.AddKeysAndValues(knv); lvi.Tag = pi; // keep track of the placeitem }
/// <summary> /// Fills the list with all the places in a PlaceListSettings class (used to serialize places) /// </summary> /// <param name="pls">The PlaceListSettings class that contains all the places</param> public void FillListFromSettings(PlaceListSettings pls) { // clear the list this.Items.Clear(); if(pls.places == null) return; // nothing to do foreach(PlaceListSettings.PlaceData pd in pls.places) { PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); pi.pn.Name = pd.Name; pi.pn.Lat = (float)pd.Lat; pi.pn.Lon = (float)pd.Lon; pi.pn.metaData = new Hashtable(); for(int i=0; i < pd.metadata.Length; i++) { pi.pn.metaData.Add(pd.metadata[i].name, pd.metadata[i].value); } AddPlace(pi); } }
/// <summary> /// Adds a place given a PlaceItem /// </summary> /// <param name="pi">PlaceItem class describing the place</param> public void AddPlace(PlaceItem pi) { Hashtable knv = new Hashtable(); // holds name/value pairs // add the "standard" attributes to the hashtable knv.Add("Name", pi.pn.Name); // pi.strPlaceName); knv.Add("Layer", pi.placeDescriptor == null ? "" : pi.placeDescriptor.Name.Value); knv.Add("Latitude", pi.pn.Lat.ToString()); // pi.lat.ToString()); knv.Add("Longitude", pi.pn.Lon.ToString()); // pi.lon.ToString()); // now add metadata attributes if(pi.pn.metaData != null) { foreach(DictionaryEntry de in pi.pn.metaData) { knv.Add(de.Key, de.Value); } } // add to the list via the hashtable ListViewItem lvi = this.AddKeysAndValues(knv); lvi.Tag = pi; // keep track of the placeitem }
/// <summary> /// Loads places from a file in GPX format, given pathname /// </summary> /// <param name="strGpxPath">The file (with full path) in GPX format to load from</param> public void LoadFromGpx(string strGpxPath) { if(!File.Exists(strGpxPath)) return; XmlSerializer ser = new XmlSerializer(typeof(gpxType)); TextReader tr = new StreamReader(strGpxPath); gpxType gpx = null; try { gpx = (gpxType)ser.Deserialize(tr); } catch(Exception caught) { // TODO: log error System.Diagnostics.Debug.WriteLine(caught.InnerException.ToString()); } tr.Close(); if(gpx == null || gpx.wpt == null) return; foreach(wptType wpt in gpx.wpt) { PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); pi.pn.Name = wpt.name; pi.pn.Lat = (float)wpt.lat; pi.pn.Lon = (float)wpt.lon; AddPlace(pi); } }
// perform a full search in a placename set, with attributes bool PlaceNameSetFullSearch(string [] searchTokens, IndexedTiledPlaceNameSet curIndexedTiledSet) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName( Path.Combine( Path.GetDirectoryName(Application.ExecutablePath), curIndexedTiledSet.placenameSet.PlacenameListFilePath.Value))); // ignore this set if the corresponding directory does not exist for some reason if(!dir.Exists) return true; // loop over all WWP files in directory foreach(FileInfo placenameFile in dir.GetFiles("*.wwp")) { using(BinaryReader reader = new BinaryReader(placenameFile.OpenRead()) ) { int placenameCount = reader.ReadInt32(); // loop over all places for(int i = 0; i < placenameCount; i++) { // return false if stop requested if(CheckStopRequested()) return false; // instantiate and read current placename WorldWindPlacename pn = new WorldWindPlacename(); WplIndex.ReadPlaceName(reader, ref pn, WplIndex.MetaDataAction.Store); // if we have a match ... if(isPlaceMatched(searchTokens, pn)) { if(CheckMaxResults()) return false; PlaceItem pi = new PlaceItem(); pi.pn = pn; pi.placeDescriptor = curIndexedTiledSet.placenameSet; // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); } } } } return true; // go on }
// given an index descriptor, seek to and return place information PlaceItem GetPlaceItemFromIndexEntry(WplIndexEntry ie, MetaDataAction metaDataAction) { using( BinaryReader brWwp = OpenWwpReader(ie.fileNumber) ) { // seek to the relevant info brWwp.BaseStream.Seek(ie.seekOffset, SeekOrigin.Begin); // create a new PlaceItem PlaceItem pi = new PlaceItem(); pi.pn = new WorldWindPlacename(); // set placeNameSet info pi.placeDescriptor = this.m_placeNameSet; // now read the rest from the WWP file ReadPlaceName(brWwp, ref pi.pn, metaDataAction); return pi; } }