示例#1
0
 public static void OpenGeoLocations(FactLocation location, IProgress <string> outputText)
 {
     try
     {
         GeocodeLocations geoLocations = null;
         foreach (Form f in Application.OpenForms)
         {
             if (f is GeocodeLocations)
             {
                 f.BringToFront();
                 f.Focus();
                 geoLocations = (GeocodeLocations)f;
                 break;
             }
         }
         if (geoLocations == null)
         {
             geoLocations = new GeocodeLocations(outputText);
             geoLocations.Show();
         }
         // we now have opened form
         geoLocations.SelectLocation(location);
     }
     catch (Exception) { }
 }
示例#2
0
        public static GeoResponse CallGoogleGeocode(FactLocation address, string text)
        {
            string bounds = string.Empty;
            string tld    = address.IsUnitedKingdom ? "&region=uk" : string.Empty;

            if (address != null)
            {
                //if (address.Level > FactLocation.SUBREGION)
                //{
                //    FactLocation area = address.GetLocation(FactLocation.SUBREGION);
                //    if (area != null && area.IsGeoCoded(false) && !string.IsNullOrEmpty(area.Bounds))
                //        bounds = $"{area.Bounds}";
                //}
                if (string.IsNullOrEmpty(bounds) && address.Level > FactLocation.REGION)
                {
                    FactLocation area = address.GetLocation(FactLocation.REGION);
                    if (area != null && area.IsGeoCoded(false) && !string.IsNullOrEmpty(area.Bounds))
                    {
                        bounds = $"{area.Bounds}";
                    }
                }
                if (string.IsNullOrEmpty(bounds) && address.Level > FactLocation.COUNTRY)
                {
                    FactLocation area = address.GetLocation(FactLocation.COUNTRY);
                    if (area != null && area.IsGeoCoded(false) && !string.IsNullOrEmpty(area.Bounds))
                    {
                        bounds = $"{area.Bounds}";
                    }
                }
            }
            string encodedAddress = HttpUtility.UrlEncode(text.Replace(" ", "+"));
            string url            = $"https://maps.googleapis.com/maps/api/geocode/json?address={encodedAddress}{bounds}{tld}&key={GoogleAPIKey.KeyValue}";

            return(GetGeoResponse(url));
        }
示例#3
0
 void EditLocation_FormClosing(object sender, FormClosingEventArgs e)
 {
     // If point updated and we are warning then warn
     if (pointUpdated)
     {
         UserSavedPoint = false;
         DialogResult result = DialogResult.Yes;
         if (Application.UserAppDataRegistry.GetValue("Ask to update database", "True").Equals("True"))
         {
             result = MessageBox.Show("Do you want to save this new position", "Save changes",
                                      MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
         }
         if (result == DialogResult.Cancel)
         {
             e.Cancel = true;
             FactLocation.CopyLocationDetails(originalLocation, location);
         }
         else if (result == DialogResult.No)
         {
             FactLocation.CopyLocationDetails(originalLocation, location);
             pointUpdated = false;
         }
         else if (result == DialogResult.Yes)
         {
             UpdateDatabase();
             UserSavedPoint = true;
         }
     }
 }
示例#4
0
        public static Predicate <T> IncompleteDataFilter <T>(int level, Predicate <T> certificatePresent,
                                                             Func <T, FactDate> filterDate, Func <FactDate, T, FactLocation> filterLocation)
        {
            return(t =>
            {
                if (certificatePresent(t))
                {
                    return false;
                }
                FactDate fd = filterDate(t);
                if (fd is null || !fd.IsExact)
                {
                    return true;
                }
                FactLocation l = filterLocation(fd, t);
                switch (level)
                {
                case FactLocation.COUNTRY: return (l.Country.Length == 0);

                case FactLocation.REGION: return (l.Region.Length == 0);

                case FactLocation.SUBREGION: return (l.SubRegion.Length == 0);

                case FactLocation.ADDRESS: return (l.Address.Length == 0);

                case FactLocation.PLACE: return (l.Place.Length == 0);

                default: return true;
                }
            });
        }
示例#5
0
        private bool IsValidIndividual(CensusIndividual indiv, bool censusDone, bool parentCheck, bool checkCensus)
        {
            if (indiv == null)
            {
                return(false);
            }
            DateTime     birth        = indiv.BirthDate.StartDate;
            DateTime     death        = indiv.DeathDate.EndDate;
            FactLocation bestLocation = indiv.BestLocation(CensusDate);

            if (birth <= CensusDate.StartDate && death >= CensusDate.StartDate)
            {
                if ((checkCensus && indiv.IsCensusDone(CensusDate) == censusDone && !indiv.OutOfCountry(CensusDate)) || !checkCensus)
                {
                    if (parentCheck) // Husband or Wife with valid date range
                    {
                        return(true);
                    }
                    else // individual is a child so remove if married before census date
                    {
                        return(!indiv.IsMarried(CensusDate));
                    }
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
示例#6
0
        public void SetLocation(FactLocation loc, int level)
        {
            this.Text = "Individuals & Families with connection to " + loc.ToString();
            level     = Math.Min(loc.Level, level); // if location level isn't as detailed as level on tab use location level
            IEnumerable <Individual> listInd = ft.GetIndividualsAtLocation(loc, level);
            SortableBindingList <IDisplayIndividual> dsInd = new SortableBindingList <IDisplayIndividual>();

            foreach (Individual i in listInd)
            {
                dsInd.Add(i);
            }
            dgIndividuals.DataSource = dsInd;
            SortIndividuals();

            IEnumerable <Family> listFam = ft.GetFamiliesAtLocation(loc, level);
            SortableBindingList <IDisplayFamily> dsFam = new SortableBindingList <IDisplayFamily>();

            foreach (Family f in listFam)
            {
                dsFam.Add(f);
            }
            dgFamilies.DataSource = dsFam;
            SortFamilies();
            splitContainer.Panel2Collapsed = false;
            UpdateStatusCount();
        }
示例#7
0
 protected static void OnGeoLocationUpdated(FactLocation loc)
 {
     if (GeoLocationUpdated != null)
     {
         GeoLocationUpdated(loc, EventArgs.Empty);
     }
 }
示例#8
0
        public void RefreshTreeNodeIcon(FactLocation location)
        {
            string[] parts    = location.GetParts();
            TreeNode currentM = mainformTreeRootNode;
            TreeNode currentP = placesTreeRootNode;

            foreach (string part in parts)
            {
                if (part.Length == 0 && !Properties.GeneralSettings.Default.AllowEmptyLocations)
                {
                    break;
                }
                if (mainformTreeRootNode != null && currentM != null)
                {
                    TreeNode childM = currentM.Nodes.Find(part, false).FirstOrDefault();
                    currentM = childM;
                }
                if (placesTreeRootNode != null && currentP != null)
                {
                    TreeNode childP = currentP.Nodes.Find(part, false).FirstOrDefault();
                    currentP = childP;
                }
            }
            // we should now have nodes to update
            if (mainformTreeRootNode != null && currentM != null)
            {
                SetTreeNodeImage(location, currentM);
            }
            if (placesTreeRootNode != null && currentP != null)
            {
                SetTreeNodeImage(location, currentP);
            }
        }
示例#9
0
        public static List <MapLocation> YearMapLocations(FactDate when, int limit)
        {
            List <MapLocation> result = new List <MapLocation>();

            foreach (Individual ind in FamilyTree.Instance.AllIndividuals)
            {
                if (ind.IsAlive(when) && ind.GetMaxAge(when) < FactDate.MAXYEARS)
                {
                    Fact         fact = ind.BestLocationFact(when, limit);
                    FactLocation loc  = fact.Location;
                    if (loc.IsGeoCoded(false))
                    {
                        result.Add(new MapLocation(ind, fact, when));
                    }
                    else
                    {
                        int startlevel = loc.Level - 1;
                        for (int level = startlevel; level > FactLocation.UNKNOWN; level--)
                        {
                            loc = loc.GetLocation(level);
                            if (loc.IsGeoCoded(false))
                            {
                                result.Add(new MapLocation(ind, fact, loc, when));
                                break;
                            }
                        }
                    }
                }
            }
            return(result);
        }
        public bool Process(CensusDate censusDate, bool censusDone, bool checkCensus)
        {
            bool result = false;
            var  facts  = new List <Fact>();

            CensusDate = censusDate;
            if (IsValidFamily()) // valid family is one where any member is alive on census
            {
                if (censusDate == CensusDate.UKCENSUS1841)
                {
                    Console.Write("break");
                }
                if (IsValidIndividual(Wife, censusDone, true, checkCensus))
                {
                    result = true;
                    facts.AddRange(Wife.PersonalFacts);
                }
                else
                {
                    Wife = null;
                }
                // overwrite bestLocation by husbands as most commonly the family
                // end up at husbands location after marriage
                if (IsValidIndividual(Husband, censusDone, true, checkCensus))
                {
                    result = true;
                    facts.AddRange(Husband.PersonalFacts);
                }
                else
                {
                    Husband = null;
                }
                // update bestLocation by marriage date as Husband and Wife
                // locations are often birth locations
                var marriage = GetPreferredFact(Fact.MARRIAGE);
                if (marriage != null)
                {
                    facts.Add(marriage);
                }

                var censusChildren = new List <CensusIndividual>();
                // sort children oldest first
                Children.Sort(new CensusAgeComparer());
                foreach (var child in Children)
                {
                    // set location to childs birth location
                    // this will end up setting birth location of last child
                    // as long as the location is at least Parish level
                    if (IsValidIndividual(child, censusDone, false, checkCensus))
                    {
                        result = true;
                        censusChildren.Add(child);
                        facts.AddRange(child.PersonalFacts);
                    }
                }
                Children     = censusChildren;
                BestLocation = FactLocation.BestLocation(facts, censusDate);
            }
            return(result);
        }
        public static void StoreLostCousinsFact(CensusIndividual ind, IProgress <string> outputText)
        {
            try
            {
                if (InstanceConnection.State != ConnectionState.Open)
                {
                    InstanceConnection.Open();
                }
                SqliteParameter param;

                using (SqliteCommand cmd = new SqliteCommand("insert into LostCousins (CensusYear, CensusCountry, CensusRef, IndID, FullName) values(?,?,?,?,?)", InstanceConnection))
                {
                    param        = cmd.CreateParameter();
                    param.DbType = DbType.Int32;
                    cmd.Parameters.Add(param);
                    param        = cmd.CreateParameter();
                    param.DbType = DbType.String;
                    cmd.Parameters.Add(param);
                    param        = cmd.CreateParameter();
                    param.DbType = DbType.String;
                    cmd.Parameters.Add(param);
                    param        = cmd.CreateParameter();
                    param.DbType = DbType.String;
                    cmd.Parameters.Add(param);
                    param        = cmd.CreateParameter();
                    param.DbType = DbType.String;
                    cmd.Parameters.Add(param);
                    cmd.Prepare();

                    if (ind.CensusReference != null)
                    {
                        cmd.Parameters[0].Value = ind.CensusDate.BestYear;
                        cmd.Parameters[1].Value = ind.CensusCountry;
                        cmd.Parameters[2].Value = ind.CensusReference;
                        cmd.Parameters[3].Value = ind.IndividualID;
                        cmd.Parameters[4].Value = ind.Name;

                        int rowsaffected = cmd.ExecuteNonQuery();
                        if (rowsaffected != 1)
                        {
                            outputText.Report($"\nProblem updating record in database update affected {rowsaffected} records.");
                        }
                        else
                        {
                            FactLocation location = FactLocation.GetLocation(ind.CensusCountry);
                            Fact         f        = new Fact(ind.CensusRef, Fact.LC_FTA, ind.CensusDate, location, string.Empty, true, true);
                            Individual   person   = FamilyTree.Instance.GetIndividual(ind.IndividualID); // get the individual not the census indvidual
                            person?.AddFact(f);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                outputText.Report($"\nFailed to save Lost Cousins record in database error was: {e.Message}");
            }
        }
示例#12
0
        public ScottishParish(string RD, string name, string region)
        {
            this.RD     = RD;
            this.Name   = name;
            this.Region = region;
            string loc = name + ", " + region + ", Scotland";

            this.Location = FactLocation.GetLocation(loc, false);
        }
示例#13
0
        // Call geocoding routine but account for throttling by Google geocoding engine
        public static GeoResponse GoogleGeocode(FactLocation address, string text, int badtries)
        {
            int    maxInterval = 30000;
            double seconds     = sleepinterval / 1000;

            if (sleepinterval > 500 && seconds > 0.1)
            {
                OnWaitingForGoogle($"Google Timeout. Waiting {seconds} seconds.");
            }
            if (sleepinterval >= maxInterval)
            {
                return(MaxedOut());
            }
            for (int interval = 0; interval < sleepinterval; interval += 1000)
            {
                Thread.Sleep(1000);
                if (ThreadCancelled)
                {
                    return(null);
                }
            }
            GeoResponse res;

            try
            {
                res = CallGoogleGeocode(address, text);
            }
            catch (Exception e)
            {
                OnWaitingForGoogle($"Caught exception: {e}");
                res = null;
            }
            if (res == null || res.Status == "OVER_QUERY_LIMIT")
            {
                // we're hitting Google too fast, increase interval
                sleepinterval = Math.Min(sleepinterval + ++badtries * 750, maxInterval);
                return(GoogleGeocode(address, text, badtries));
            }
            else
            {
                if (res != null && res.Status != "REQUEST_DENIED")
                {
                    OnWaitingForGoogle(string.Empty); // going well clear any previous message
                                                      // no throttling, go a little bit faster
                    if (sleepinterval > 10000)
                    {
                        sleepinterval = 200;
                    }
                    else
                    {
                        sleepinterval = Math.Max(sleepinterval / 2, 75);
                    }
                }
                return(res);
            }
        }
示例#14
0
 public Fact(string factRef, string factType, FactDate date, FactLocation loc, string comment = "", bool preferred = true, bool createdByFTA = false)
     : this(factRef, preferred)
 {
     this.FactType = factType;
     this.FactDate = date;
     this.Comment  = comment;
     this.Created  = createdByFTA;
     this.Place    = string.Empty;
     this.Location = loc;
 }
示例#15
0
 public MapLocation(Individual ind, Fact fact, FactLocation loc, FactDate year)
 {
     this.Individual    = ind;
     this.Fact          = fact;
     this.Location      = loc;
     this.year          = year;
     this.Icon          = FactLocationImage.ErrorIcon(loc.GeocodeStatus).Icon;
     this.Geometry      = new NetTopologySuite.Geometries.Point(Location.LongitudeM, Location.LatitudeM);
     this.FoundLocation = loc.FoundLocation;
 }
示例#16
0
        private static void SetTreeNodeImage(FactLocation location, TreeNode child)
        {
            if (child == null)
            {
                return;
            }
            switch (location.GeocodeStatus)
            {
            case FactLocation.Geocode.NOT_SEARCHED:
                child.ImageIndex   = 0;
                child.ToolTipText += "\nUse 'Run Google Geocoder' option under Maps menu to search Google for location.";
                break;

            case FactLocation.Geocode.MATCHED:
                child.ImageIndex = 1;
                break;

            case FactLocation.Geocode.PARTIAL_MATCH:
                child.ImageIndex = 2;
                break;

            case FactLocation.Geocode.GEDCOM_USER:
                child.ImageIndex = 3;
                break;

            case FactLocation.Geocode.NO_MATCH:
                child.ImageIndex = 4;
                break;

            case FactLocation.Geocode.INCORRECT:
                child.ImageIndex = 5;
                break;

            case FactLocation.Geocode.OUT_OF_BOUNDS:
                child.ImageIndex = 6;
                break;

            case FactLocation.Geocode.LEVEL_MISMATCH:
                child.ImageIndex = 7;
                break;

            case FactLocation.Geocode.OS_50KMATCH:
                child.ImageIndex = 8;
                break;

            case FactLocation.Geocode.OS_50KPARTIAL:
                child.ImageIndex = 9;
                break;

            case FactLocation.Geocode.OS_50KFUZZY:
                child.ImageIndex = 10;
                break;
            }
        }
示例#17
0
 public bool IsAtLocation(FactLocation loc, int level)
 {
     foreach (Fact f in AllFamilyFacts)
     {
         if (f.Location.Equals(loc, level))
         {
             return(true);
         }
     }
     return(false);
 }
        static void AddLostCousinsFact(CensusIndividual ind)
        {
            FactLocation location = FactLocation.GetLocation(ind.CensusCountry);
            Fact         f        = new Fact(ind.CensusRef, Fact.LC_FTA, ind.CensusDate, location, string.Empty, true, true);
            Individual   person   = FamilyTree.Instance.GetIndividual(ind.IndividualID); // get the individual not the census indvidual

            if (person != null && !person.HasLostCousinsFactAtDate(ind.CensusDate))
            {
                person.AddFact(f);
            }
        }
示例#19
0
        private void EditLocation(FactLocation loc)
        {
            EditLocation editform = new EditLocation(loc);

            this.Cursor = Cursors.Default;
            DialogResult result = editform.ShowDialog(this);

            editform.Dispose(); // needs disposed as it is only hidden because it is a modal dialog
            // force refresh of locations from new edited data
            dgIndividuals.Refresh();
        }
示例#20
0
 void UpdateIcons(FactLocation changed)
 {
     foreach (MapLocation loc in locations)
     {
         if (loc.Location.Equals(changed))
         {
             loc.UpdateIcon();
         }
     }
     dgIndividuals.Refresh();
 }
        public override int Compare(CensusIndividual r1, CensusIndividual r2)
        {
            FactLocation l1   = r1.CensusLocation;
            FactLocation l2   = r2.CensusLocation;
            int          comp = l1.CompareTo(l2, level);

            if (comp == 0)
            {
                comp = base.Compare(r1, r2);
            }
            return(comp);
        }
示例#22
0
 public void ShowLocation(FactLocation loc, int level)
 {
     if (loc.IsGeoCoded(false))
     {
         string URL = $"https://www.google.com/maps/@{loc.Latitude},{loc.Longitude},{level}z";
         SpecialMethods.VisitWebsite(URL);
     }
     else
     {
         MessageBox.Show($"{loc.ToString()} is not yet geocoded so can't be displayed.");
     }
 }
示例#23
0
 public void GetLocationDetails(FactLocation location)
 {
     if (location.ToString().Length == 0)
     {
         return;
     }
     using (SQLiteConnection conn = new SQLiteConnection(connectionString))
     {
         conn.Open();
         ReadLocationIntoFact(location, conn);
     }
 }
示例#24
0
 public static void GetLocationDetails(FactLocation location)
 {
     if (location.ToString().Length == 0)
     {
         return;
     }
     if (InstanceConnection.State != ConnectionState.Open)
     {
         InstanceConnection.Open();
     }
     ReadLocationIntoFact(location, InstanceConnection);
 }
示例#25
0
        public static bool IsCensusCountry(FactDate fd, FactLocation location)
        {
            List <CensusDate> matches = SUPPORTED_CENSUS.Where(cd => cd.Country.Equals(location.CensusCountry)).ToList();

            foreach (CensusDate cd in matches)
            {
                if (fd.YearMatches(cd))
                {
                    return(true);
                }
            }
            return(false);
        }
示例#26
0
        public bool SetLocation(FactLocation loc, int level)
        {
            while (!loaded)
            {
                Application.DoEvents();
            }
            GeoResponse.CResult.CGeometry.CViewPort viewport = null;
            GeoResponse res = null;

            Object[] args = new Object[] { 0, 0 };
            if (loc.IsGeoCoded(false) && loc.ViewPort != null)
            {
                labMapLevel.Text = "Previously Geocoded: " + loc.ToString();
                viewport         = MapTransforms.ReverseTransformViewport(loc.ViewPort);
                args             = new Object[] { loc.Latitude, loc.Longitude };
            }
            else
            {
                location = loc.ToString();
                res      = CallGoogleGeocode(location);
                if (res.Status == "OK")
                {
                    labMapLevel.Text = GoogleMap.LocationText(res, loc, level);
                    viewport         = res.Results[0].Geometry.ViewPort;
                    double lat = res.Results[0].Geometry.Location.Lat;
                    double lng = res.Results[0].Geometry.Location.Long;
                    args = new Object[] { lat, lng };
                }
                else if (res.Status == "OVER_QUERY_LIMIT" && loc.IsGeoCoded(false))
                {
                    labMapLevel.Text        = "Previously Geocoded: " + loc.ToString();
                    viewport                = new GeoResponse.CResult.CGeometry.CViewPort();
                    viewport.NorthEast.Lat  = loc.Latitude + 2;
                    viewport.NorthEast.Long = loc.Longitude + 2;
                    viewport.SouthWest.Lat  = loc.Latitude - 2;
                    viewport.SouthWest.Long = loc.Longitude - 2;
                    args = new Object[] { loc.Latitude, loc.Longitude };
                }
                else
                {
                    return(false);
                }
            }
            Object marker = webBrowser.Document.InvokeScript("frontAndCenter", args);

            args = new Object[] { viewport.NorthEast.Lat, viewport.NorthEast.Long, viewport.SouthWest.Lat, viewport.SouthWest.Long };
            webBrowser.Document.InvokeScript("setViewport", args);
            webBrowser.Show();
            return(true);
        }
示例#27
0
        void TvPlaces_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            Cursor = Cursors.WaitCursor;;
            FactLocation location = e.Node.Tag as FactLocation;

            if (location != null)
            {
                People frmInd = new People();
                frmInd.SetLocation(location, e.Node.Level);
                MainForm.DisposeDuplicateForms(frmInd);
                frmInd.Show();
            }
            Cursor = Cursors.Default;
        }
示例#28
0
 public static bool ContainsLocation(this IList <FactLocation> list, FactLocation loc)
 {
     if (list != null)
     {
         for (int i = 0; i < list.Count; i++)
         {
             if (list[i] == loc)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
示例#29
0
 private void SetCommentAndLocation(string factType, string factComment, string factPlace, string latitude, string longitude)
 {
     if (factComment.Length == 0 && factPlace.Length > 0)
     {
         if (factPlace.EndsWith("/"))
         {
             Comment = factPlace.Substring(0, factPlace.Length - 1);
             Place   = string.Empty;
         }
         else
         {
             int slash = factPlace.IndexOf("/");
             if (slash >= 0)
             {
                 Comment = factPlace.Substring(0, slash).Trim();
                 // If slash occurs at end of string, location is empty.
                 Place = (slash == factPlace.Length - 1) ? string.Empty : factPlace.Substring(slash + 1).Trim();
             }
             else if (Fact.COMMENT_FACTS.Contains(factType))
             {
                 // we have a comment rather than a location
                 Comment = factPlace;
                 Place   = string.Empty;
             }
             else
             {
                 Comment = string.Empty;
                 Place   = factPlace;
             }
         }
     }
     else
     {
         Comment = factComment;
         Place   = factPlace;
         if (factType == NAME)
         {
             Comment = Comment.Replace("/", "");
         }
     }
     Comment = EnhancedTextInfo.ToTitleCase(Comment).Trim();
     if (Properties.GeneralSettings.Default.ReverseLocations)
     {
         Location = FactLocation.GetLocation(ReverseLocation(Place), latitude, longitude, FactLocation.Geocode.NOT_SEARCHED);
     }
     else
     {
         Location = FactLocation.GetLocation(Place, latitude, longitude, FactLocation.Geocode.NOT_SEARCHED);
     }
 }
示例#30
0
 static void ReadLocationIntoFact(FactLocation location, SQLiteConnection conn)
 {
     using (SQLiteCommand cmd = new SQLiteCommand("select latitude, longitude, latm, longm, viewport_x_ne, viewport_y_ne, viewport_x_sw, viewport_y_sw, geocodestatus, foundlevel, foundlocation, foundresulttype from geocode where location = ?", conn))
     {
         SQLiteParameter param = cmd.CreateParameter();
         param.DbType = DbType.String;
         cmd.Parameters.Add(param);
         cmd.Prepare();
         cmd.Parameters[0].Value = location.ToString();
         using (SQLiteDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
         {
             if (reader.Read())
             {
                 double.TryParse(reader["latitude"].ToString(), out double latitude);
                 double.TryParse(reader["longitude"].ToString(), out double longitude);
                 double.TryParse(reader["latm"].ToString(), out double latm);
                 double.TryParse(reader["longm"].ToString(), out double longm);
                 double.TryParse(reader["viewport_x_ne"].ToString(), out double viewport_x_ne);
                 double.TryParse(reader["viewport_y_ne"].ToString(), out double viewport_y_ne);
                 double.TryParse(reader["viewport_x_sw"].ToString(), out double viewport_x_sw);
                 double.TryParse(reader["viewport_y_sw"].ToString(), out double viewport_y_sw);
                 location.Latitude   = latitude;
                 location.Longitude  = longitude;
                 location.LatitudeM  = latm;
                 location.LongitudeM = longm;
                 if (location.ViewPort == null)
                 {
                     location.ViewPort = new GeoResponse.CResult.CGeometry.CViewPort
                     {
                         NorthEast = new GeoResponse.CResult.CGeometry.CLocation(),
                         SouthWest = new GeoResponse.CResult.CGeometry.CLocation()
                     };
                 }
                 location.ViewPort.NorthEast.Lat  = viewport_y_ne;
                 location.ViewPort.NorthEast.Long = viewport_x_ne;
                 location.ViewPort.SouthWest.Lat  = viewport_y_sw;
                 location.ViewPort.SouthWest.Long = viewport_x_sw;
                 location.GeocodeStatus           = (FactLocation.Geocode)Enum.Parse(typeof(FactLocation.Geocode), reader["geocodestatus"].ToString());
                 location.FoundLocation           = reader["foundlocation"].ToString();
                 location.FoundResultType         = reader["foundresulttype"].ToString();
                 int.TryParse(reader["foundlevel"].ToString(), out int foundlevel);
                 location.FoundLevel = foundlevel;
             }
         }
     }
 }