# How to setup a NASA WorldWind feature server (WFS) ## Ubuntu 18.04.4 LTS Initial Setup ### Change root password ``` Changing password for root. (current) UNIX password: Enter new UNIX password: Retype new UNIX password: ``` ### Add new user and set password ```bash adduser xxx chgpasswd ``` ### Update the firewall ```bash $ ufw app list Available applications: OpenSSH $ sudo ufw allow OpenSSH Rules update Rules updated (v6) $ sudo ufw enable Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup $ sudo ufw status Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) ``` ## Install Tomcat Application Server ### Install Java (for Tomcat and GeoServer) ```bash sudo apt-get update sudo apt-get install default-jdk ``` ### Install Tomcat - Create a `tomcat` group - Create a `tomcat` user - Download a Tomcat distribution to `/tmp` - Extract the distribution to `/opt/tomcat` - Adjust the permissions of `/opt/tomcat` See: [https://www.digitalocean.com/community/tutorials/install-tomcat-9-ubuntu-1804](https://www.digitalocean.com/community/tutorials/install-tomcat-9-ubuntu-1804) ```bash sudo groupadd tomcat sudo useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat cd /tmp curl -O http://www-us.apache.org/dist/tomcat/tomcat-9/v9.0.17/bin/apache-tomcat-9.0.17.tar.gz sudo mkdir /opt/tomcat sudo tar xzvf apache-tomcat-9*tar.gz -C /opt/tomcat --strip-components=1 cd /opt/tomcat/ /opt/tomcat$ sudo chgrp -R tomcat /opt/tomcat /opt/tomcat$ sudo chmod -R g+r conf /opt/tomcat$ sudo chmod g+x conf /opt/tomcat$ sudo chown -R tomcat webapps/ work/ temp/ logs ``` ### Update Tomcat service - Get location of JAVA - Create tomcat.service file - Update service JAVA_HOME with JAVA location - Start Tomcat - Enable Tomcat service at startup Get the path to Java ```bash sudo update-java-alternatives -l ``` _Example output_ ```bash java-1.11.0-openjdk-amd64 1101 /usr/lib/jvm/java-1.11.0-openjdk-amd64 ``` ```bash sudo nano /etc/systemd/system/tomcat.service ``` Paste the following into the tomcat.service file and edit the JAVA_HOME path: ```properties [Unit] Description=Apache Tomcat Web Application Container After=network.target [Service] Type=forking Environment=JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64 Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid Environment=CATALINA_HOME=/opt/tomcat Environment=CATALINA_BASE=/opt/tomcat Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC' Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom' ExecStart=/opt/tomcat/bin/startup.sh ExecStop=/opt/tomcat/bin/shutdown.sh User=tomcat Group=tomcat UMask=0007 RestartSec=10 Restart=always [Install] WantedBy=multi-user.target ``` Reload the service, start and enable the service. ```bash sudo systemctl daemon-reload sudo systemctl start tomcat sudo systemctl status tomcat sudo systemctl enable tomcat ``` ### Configure firewall to allow port 8080 (Tomcat) ```bash $ sudo ufw allow 8080 Rule added Rule added (v6) ``` ### Configure Tomcat users ``` bash $ sudo nano /opt/tomcat/webapps/host-manager/META-INF/context.xml $ sudo nano /opt/tomcat/conf/tomcat-users.xml $ sudo systemctl restart tomcat $ sudo systemctl status tomcat ``` _tomcat.users_ ``` ``` ### Allow manager app to be run by remote systems * Edit context.xml * Comment out default `allow=ip-address` or add remote ip address ``` sudo nano /opt/tomcat/webapps/manager/META-INF/context.xml ``` _context.xml_ ``` . . . JKMount /* ajp13_worker . . . ``` Restart Apache and then test http://localhost (or https://localhost) in your browser and validate the Tomcat home page is displayed. ```bash sudo systemctl restart apache2 ``` ### Adding CORS support: Header set Access-Control-Allow-Origin "\*" Edit your Apache configuration file(s) and add the Access-Control-Allow-Origin header ```bash sudo nano /etc/apache2/sites-available/000-default-le-ssl.conf sudo nano /etc/apache2/sites-available/000-default.conf ``` _Example_ ``` . . . Header set Access-Control-Allow-Origin "*" . . . ``` Validate and restart. ```bash sudo apache2ctl configtest sudo systemctl restart apache2 ``` ### Enable Apache modules Enable the specified modules and restart Apache ```bash sudo a2enmod headers sudo a2enmod rewrite sudo a2enmod deflate sudo systemctl restart apache2 sudo systemctl status apache2 ``` ## Setup GeoServer ### Download GeoServer Visit the GeoServer (https://geoserver.org site and get the direct download link to the `war` servlet download for the latest release. Use this link to download the file with `curl` or simply download interactively via your browser. ```bash cd \tmp curl -O https://downloads.sourceforge.net/project/geoserver/GeoServer/2.15.0/geoserver-2.15.0-war.zip?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fgeoserver%2Ffiles%2FGeoServer%2F2.15.0%2Fgeoserver-2.15.0-war.zip%2Fdownload ``` ### Install GeoServer using the Tomcat Manager 1. Extract the `geoserver.war` file from the downloaded release. 2. Edit the `webapps/manager/WEB-INF/web.xml` to allow large .war files to be deployed. Otherwise the following error may occur: _manager.log snippet_ ```text FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (102931473) exceeds the configured maximum (52428800)] ``` _The original webapps/manager/WEB-INF/web.xml is constraned to 50MB_ ```xml HTMLManager ... 52428800 52428800 0 ``` _This webapps/manager/WEB-INF/web.xml snippet is large enough for geoserver.war_ ```xml HTMLManager ... 1200000000 1200000000 0 ``` 3. Using a browser, access your Tomcat server's home page and log in to the Manager app. - Deploy the `geoserver.war` file ### Configure GeoServer 1. Change the admin password! --- ## Setup PostGIS See: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postgis-on-ubuntu-14-04 ``` sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable sudo apt-get update sudo apt-get install postgis ``` > Success. You can now start the database server using: > > /usr/lib/postgresql/10/bin/pg_ctl -D /var/lib/postgresql/10/main -l logfile start The installation procedure created a user account called `postgres` that is associated with the default Postgres role. In order to use Postgres, we'll need to log into that account. You can do that by typing: ``` sudo -i -u postgres ``` ### Restore databases #### 1. Create the `geonames` and `places` PostGIS databases using `psql`. First login as the `postgres` user. ```bash sudo -i -u postgres ``` Now create the databases using `psql` with the PostGIS extension, as follows: ``` postgres:~$ psql psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1)) Type "help" for help. ``` Create the databases: ```sql postgres=# create database geonames; CREATE DATABASE ``` ```sql postgres=# create database places; CREATE DATABASE ``` Add the PostGIS extensions: ```sql postgres=# \c geonames; You are now connected to database "geonames" as user "postgres". ``` ```sql geonames=# create extension postgis; CREATE EXTENSION ``` ```sql geonames=# \c places You are now connected to database "places" as user "postgres". ``` ```sql places=# create extension postgis; CREATE EXTENSION ``` Quite psql ```sql places=# **\q** ``` #### 2. Now we will restore the databases using `pg_restore' We will restore the databases from a previous backup created with `pg_dump`. Numerous errors will be reported as the backups were created with earlier version of Postgres. ```bash pg_restore -d places ww22dumpplaces pg_restore -d geonames ww22dumpgeonames ``` Validate the databases by comparing the content below with your `\dt` describe table output. ``` postgres=# \c geonames You are now connected to database "geonames" as user "postgres". geonames=# \dt List of relations Schema | Name | Type | Owner --------+-----------------+-------+---------- public | citiesover100k | table | postgres public | citiesover10k | table | postgres public | citiesover15k | table | postgres public | citiesover1k | table | postgres public | citiesover500k | table | postgres public | citiesover50k | table | postgres public | spatial_ref_sys | table | postgres (7 rows) geonames=# \c places You are now connected to database "places" as user "postgres". places=# \dt List of relations Schema | Name | Type | Owner --------+--------------------------+-------+---------- public | cia | table | postgres public | cia2 | table | postgres public | countries | table | postgres public | geonet_20060905 | table | postgres public | geonet_20060905_adm1 | table | postgres public | geonet_20060905_adm2 | table | postgres public | geonet_20060905_capitals | table | postgres public | geonet_20060905_oceans | table | postgres public | geonet_20060905_ppl | table | postgres public | geonet_20060905_ppla | table | postgres public | spatial_ref_sys | table | postgres public | us_counties | table | postgres public | wpl_continents | table | postgres public | wpl_countries | table | postgres public | wpl_desertsplains | table | postgres public | wpl_geonet_a_adm1 | table | postgres public | wpl_geonet_a_adm2 | table | postgres public | wpl_geonet_a_adm3 | table | postgres public | wpl_geonet_p_ppl | table | postgres public | wpl_geonet_p_ppla | table | postgres public | wpl_geonet_p_pplc | table | postgres public | wpl_lakesrivers | table | postgres public | wpl_mountainsvalleys | table | postgres public | wpl_oceans | table | postgres public | wpl_trenchesridges | table | postgres public | wpl_us_anthropogenic | table | postgres public | wpl_us_terrain | table | postgres public | wpl_us_water | table | postgres public | wpl_uscities0 | table | postgres public | wpl_uscitiesover0 | table | postgres public | wpl_uscitiesover100k | table | postgres public | wpl_uscitiesover10k | table | postgres public | wpl_uscitiesover1k | table | postgres public | wpl_uscitiesover500k | table | postgres public | wpl_uscitiesover50k | table | postgres public | wpl_waterbodies | table | postgres (36 rows) places=# ``` ### Create users You will need to create a database user for GeoServer to connect to Postgres. Using `psql` we create a user named "geoserver" with a password of your choosing. You will use this user/password combination in GeoServer when connecting to the Posgres databases. First login as the `postgres` user. ```bash sudo -i -u postgres ``` Now create the user and grant priviledges to the databases: ``` psql postgres=# create user geoserver WITH PASSWORD 'password-string'; postgres=# \c geonames You are now connected to database "geonames" as user "postgres". geonames=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to geoserver; GRANT geonames=# \c places You are now connected to database "places" as user "postgres". places=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to geoserver; GRANT places=# \q ``` ## Configure GeoServer Features #### 1. Login to GeoServer #### 2. Create Stores for geonames and places Repeat these steps for both the `geonames` and `places` databases. 1. Select _Stores > Add New Store_ 2. Select _PostGIS - PostGIS Database_, and use the defaults except for the following: - Workspace: **topp** - Data Source Name: _enter the database name_ - database: _enter the database name_ - user: _geoserver user created earlier_ - passwd: _geoserver password created earlier_ 3. Select _Save_ #### 3. Create Styles used for Country Boundaries Create a style called `countryboundaries` without a namespaceL 1. Select _Styles > Add New Style_ 2. Uses the defaults except for the following: - Workspace: _leave blank_ - Name: **countryboundaries** - Style Content: ```xml Country Boundaries A boring default style A sample style that just prints out a transparent interior with a red outline Rule 1 Yellow Outline yellow outline 2 pixels wide #FFFF00 2 ``` 3. Select _Validate_ and then _Submit_ #### 4. Create Layers for geonames Repeat the following steps for these `geonames` tables - citiesover100k - citiesover10k - citiesover15k - citiesover1k - citiesover500k - citiesover50k 1. Select _Layers > Add new layer_ 2. Add a layer from: **topp:geonames** 3. Click _Publish_ for one of the aforementioned layers 4. In the _Edit Layer_ screen, use the defaults except for the following: - Native Bounding Box: **Compute from data** - Lat/Lon Bounding Box: **Compute from native bounds** - Publishing tab > Default Style: **capitals** 5. Click _Save_ #### 5. Create Layers for places Repeat the following steps for these `places` tables - cia - countries - wpl_continents - wpl_countries - wpl_desertsplains - wpl_geonet_a_adm1 - wpl_geonet_a_adm2 - wpl_geonet_p_ppl - wpl_geonet_p_ppla - wpl_geonet_p_pplc - wpl_lakesrivers - wpl_mountainsvalleys - wpl_oceans - wpl_trenchesridges - wpl_us_anthropogenic - wpl_us_terrain - wpl_us_water - wpl_uscities0 - wpl_waterbodies 1. Select _Layers > Add new layer_ 2. Add a layer from: **topp:places** 3. Click _Publish_ for one of the aforementioned layers 4. In the _Edit Layer_ screen, use the defaults except for the following: - Native Bounding Box: **Compute from data** - Lat/Lon Bounding Box: **Compute from native bounds** - Publishing tab > Default Style: for the `cia` layer select **countryboundaries**, for all others select **capitals** 5. Click _Save_ ## Enable GML2-GZIP Support The Java client makes GetFeature requests using an 'outputformat=GML2-GZiP` parameter. But contemporary version of GeoServer do not support GML2-GZIP. This issue can be mitigated in Apache by the following steps: - Rewriting the query string to replace GML2-GZIP with GML2 to satisfy GeoServer - Adding an _Accept-Encoding "gzip"_ header to the request - Adding gzip compression to XML (GML) responses using a DEFLATE filter This Apache configuration snippet demonstrates how to provide GML2-GZIP support: ```conf AddOutputFilterByType DEFLATE text/xml RequestHeader set Accept-Encoding "gzip" RewriteEngine on RewriteCond %{QUERY_STRING} ^(.*)GML2-GZIP(.*)$ RewriteRule /geoserver/wfs /geoserver/wfs?%1GML2%2 ``` --- # Reference ## Java NASAWFSPlaceNameLayer ```java public class NASAWFSPlaceNameLayer extends PlaceNameLayer { //String constants for name sets public static final String OCEANS="topp:wpl_oceans"; public static final String CONTINENTS="topp:wpl_continents"; public static final String WATERBODIES="topp:wpl_waterbodies"; public static final String TRENCHESRIDGES="topp:wpl_trenchesridges"; public static final String DESERTSPLAINS="topp:wpl_desertsplains"; public static final String LAKESRIVERS="topp:wpl_lakesrivers"; public static final String MOUNTAINSVALLEYS="topp:wpl_mountainsvalleys"; public static final String COUNTRIES="topp:wpl_countries"; public static final String GEONET_P_PPC="topp:wpl_geonet_p_pplc"; public static final String CITIESOVER500K="topp:citiesover500k"; public static final String CITIESOVER100K="topp:citiesover100k"; public static final String CITIESOVER50K="topp:citiesover50k"; public static final String CITIESOVER10K="topp:citiesover10k"; public static final String CITIESOVER1K="topp:citiesover1k"; public static final String USCITIESOVER0="topp:wpl_uscitiesover0"; public static final String USCITIES0="topp:wpl_uscities0"; public static final String US_ANTHROPOGENIC="topp:wpl_us_anthropogenic"; public static final String US_WATER="topp:wpl_us_water"; public static final String US_TERRAIN="topp:wpl_us_terrain"; public static final String GEONET_A_ADM1="topp:wpl_geonet_a_adm1"; public static final String GEONET_A_ADM2="topp:wpl_geonet_a_adm2"; public static final String GEONET_P_PPLA="topp:wpl_geonet_p_ppla"; public static final String GEONET_P_PPL="topp:wpl_geonet_p_ppl"; public static final String GEONET_P_PPLC="topp:wpl_geonet_p_pplC"; private static final String[] allNameSets={OCEANS, CONTINENTS, WATERBODIES, TRENCHESRIDGES, DESERTSPLAINS, LAKESRIVERS, MOUNTAINSVALLEYS, COUNTRIES, GEONET_P_PPC, CITIESOVER500K, CITIESOVER100K, CITIESOVER50K, CITIESOVER10K, CITIESOVER1K, USCITIESOVER0,USCITIES0, US_ANTHROPOGENIC, US_WATER, US_TERRAIN, GEONET_A_ADM1, GEONET_A_ADM2, GEONET_P_PPLA, GEONET_P_PPL}; private static List activeNamesList = Arrays.asList(allNameSets); public NASAWFSPlaceNameLayer() { super(makePlaceNameServiceSet()); } public void setPlaceNameSetsVisible(List names) { activeNamesList=names; makePlaceNameServiceSet(); } private static PlaceNameServiceSet makePlaceNameServiceSet() { final String service = "https://worldwind22.arc.nasa.gov/geoserver/wfs"; final String fileCachePath = "Earth/PlaceNames/WFSPlaceNamesVersion1.0"; PlaceNameServiceSet placeNameServiceSet = new PlaceNameServiceSet(); placeNameServiceSet.setExpiryTime(new GregorianCalendar(2008, 1, 11).getTimeInMillis()); PlaceNameService placeNameService; final boolean addVersionTag=true; //true if pointing to a new wfs server // Oceans if (activeNamesList.contains(OCEANS)) { placeNameService = new PlaceNameService(service, "topp:wpl_oceans", fileCachePath, Sector.FULL_SPHERE, GRID_1x1, java.awt.Font.decode("Arial-BOLDITALIC-12"), addVersionTag); placeNameService.setColor(new java.awt.Color(200, 200, 200)); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_A); placeNameServiceSet.addService(placeNameService, false); } // Continents if (activeNamesList.contains(CONTINENTS)) { placeNameService = new PlaceNameService(service, "topp:wpl_continents", fileCachePath, Sector.FULL_SPHERE, GRID_1x1, java.awt.Font.decode("Arial-BOLD-12"), addVersionTag); placeNameService.setColor(new java.awt.Color(255, 255, 240)); placeNameService.setMinDisplayDistance(LEVEL_G); placeNameService.setMaxDisplayDistance(LEVEL_A); placeNameServiceSet.addService(placeNameService, false); } // Water Bodies if (activeNamesList.contains(WATERBODIES)) { placeNameService = new PlaceNameService(service, "topp:wpl_waterbodies", fileCachePath, Sector.FULL_SPHERE, GRID_4x8, java.awt.Font.decode("Arial-ITALIC-10"), addVersionTag); placeNameService.setColor(java.awt.Color.cyan); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_B); placeNameServiceSet.addService(placeNameService, false); } // Trenches & Ridges if (activeNamesList.contains(TRENCHESRIDGES)) { placeNameService = new PlaceNameService(service, "topp:wpl_trenchesridges", fileCachePath, Sector.FULL_SPHERE, GRID_4x8, java.awt.Font.decode("Arial-BOLDITALIC-10"), addVersionTag); placeNameService.setColor(java.awt.Color.cyan); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_B); placeNameServiceSet.addService(placeNameService, false); } // Deserts & Plains if (activeNamesList.contains(DESERTSPLAINS)) { placeNameService = new PlaceNameService(service, "topp:wpl_desertsplains", fileCachePath, Sector.FULL_SPHERE, GRID_4x8, java.awt.Font.decode("Arial-BOLDITALIC-10"), addVersionTag); placeNameService.setColor(java.awt.Color.orange); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_B); placeNameServiceSet.addService(placeNameService, false); } // Lakes & Rivers if (activeNamesList.contains(LAKESRIVERS)) { placeNameService = new PlaceNameService(service, "topp:wpl_lakesrivers", fileCachePath, Sector.FULL_SPHERE, GRID_8x16, java.awt.Font.decode("Arial-ITALIC-10"), addVersionTag); placeNameService.setColor(java.awt.Color.cyan); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_C); placeNameServiceSet.addService(placeNameService, false); } // Mountains & Valleys if (activeNamesList.contains(MOUNTAINSVALLEYS)) { placeNameService = new PlaceNameService(service, "topp:wpl_mountainsvalleys", fileCachePath, Sector.FULL_SPHERE, GRID_8x16, java.awt.Font.decode("Arial-BOLDITALIC-10"), addVersionTag); placeNameService.setColor(java.awt.Color.orange); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_C); placeNameServiceSet.addService(placeNameService, false); } // Countries if (activeNamesList.contains(COUNTRIES)) { placeNameService = new PlaceNameService(service, "topp:countries", fileCachePath, Sector.FULL_SPHERE, GRID_4x8, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.white); placeNameService.setMinDisplayDistance(LEVEL_G); placeNameService.setMaxDisplayDistance(LEVEL_D); placeNameServiceSet.addService(placeNameService, false); } // GeoNet World Capitals if (activeNamesList.contains(GEONET_P_PPLC)) { placeNameService = new PlaceNameService(service, "topp:wpl_geonet_p_pplc", fileCachePath, Sector.FULL_SPHERE, GRID_16x32, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_D); placeNameServiceSet.addService(placeNameService, false); } // World Cities >= 500k if (activeNamesList.contains(CITIESOVER500K)) { placeNameService = new PlaceNameService(service, "topp:citiesover500k", fileCachePath, Sector.FULL_SPHERE, GRID_8x16, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0); placeNameService.setMaxDisplayDistance(LEVEL_D); placeNameServiceSet.addService(placeNameService, false); } // World Cities >= 100k if (activeNamesList.contains(CITIESOVER100K)) { placeNameService = new PlaceNameService(service, "topp:citiesover100k", fileCachePath, Sector.FULL_SPHERE, GRID_16x32, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(LEVEL_N); placeNameService.setMaxDisplayDistance(LEVEL_F); placeNameServiceSet.addService(placeNameService, false); } // World Cities >= 50k and <100k if (activeNamesList.contains(CITIESOVER50K)) { placeNameService = new PlaceNameService(service, "topp:citiesover50k", fileCachePath, Sector.FULL_SPHERE, GRID_16x32, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(LEVEL_N); placeNameService.setMaxDisplayDistance(LEVEL_H); placeNameServiceSet.addService(placeNameService, false); } // World Cities >= 10k and <50k if (activeNamesList.contains(CITIESOVER10K)) { placeNameService = new PlaceNameService(service, "topp:citiesover10k", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_I); placeNameServiceSet.addService(placeNameService, false); } // World Cities >= 1k and <10k if (activeNamesList.contains(CITIESOVER1K)) { placeNameService = new PlaceNameService(service, "topp:citiesover1k", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_K); placeNameServiceSet.addService(placeNameService, false); } // US Cities (Population Over 0) if (activeNamesList.contains(USCITIESOVER0)) { //values for masking sector pulled from wfs capabilities request Sector maskingSector = new Sector(Angle.fromDegrees(18.0), Angle.fromDegrees(70.7), Angle.fromDegrees(-176.66), Angle.fromDegrees(-66.0)); placeNameService = new PlaceNameService(service, "topp:wpl_uscitiesover0", fileCachePath, maskingSector, GRID_36x72, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_N); placeNameServiceSet.addService(placeNameService, false); } // US Cities (No Population) if (activeNamesList.contains(USCITIES0)) { //values for masking sector pulled from wfs capabilities request Sector maskingSector = new Sector(Angle.fromDegrees(-14.4), Angle.fromDegrees(71.3), Angle.fromDegrees(-176.66), Angle.fromDegrees(178.88)); placeNameService = new PlaceNameService(service, "topp:wpl_uscities0", fileCachePath, maskingSector, GRID_288x576, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.orange); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_N);//M); placeNameServiceSet.addService(placeNameService, false); } // US Anthropogenic Features if (activeNamesList.contains(US_ANTHROPOGENIC)) { placeNameService = new PlaceNameService(service, "topp:wpl_us_anthropogenic", fileCachePath, Sector.FULL_SPHERE, GRID_288x576, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.orange); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_P); placeNameServiceSet.addService(placeNameService, false); } // US Water Features if (activeNamesList.contains(US_WATER)) { placeNameService = new PlaceNameService(service, "topp:wpl_us_water", fileCachePath, Sector.FULL_SPHERE, GRID_144x288, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.cyan); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_M); placeNameServiceSet.addService(placeNameService, false); } // US Terrain Features if (activeNamesList.contains(US_TERRAIN)) { placeNameService = new PlaceNameService(service, "topp:wpl_us_terrain", fileCachePath, Sector.FULL_SPHERE, GRID_72x144, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.orange); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_O); placeNameServiceSet.addService(placeNameService, false); } // GeoNET Administrative 1st Order if (activeNamesList.contains(GEONET_A_ADM1)) { placeNameService = new PlaceNameService(service, "topp:wpl_geonet_a_adm1", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_N); placeNameServiceSet.addService(placeNameService, false); } // GeoNET Administrative 2nd Order if (activeNamesList.contains(GEONET_A_ADM2)) { placeNameService = new PlaceNameService(service, "topp:wpl_geonet_a_adm2", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.yellow); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_N); placeNameServiceSet.addService(placeNameService, false); } // GeoNET Populated Place Administrative if (activeNamesList.contains(GEONET_P_PPLA)) { placeNameService = new PlaceNameService(service, "topp:wpl_geonet_p_ppla", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-BOLD-10"), addVersionTag); placeNameService.setColor(java.awt.Color.pink); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_N); placeNameServiceSet.addService(placeNameService, false); } // GeoNET Populated Place if (activeNamesList.contains(GEONET_P_PPL)) { placeNameService = new PlaceNameService(service, "topp:wpl_geonet_p_ppl", fileCachePath, Sector.FULL_SPHERE, GRID_36x72, java.awt.Font.decode("Arial-PLAIN-10"), addVersionTag); placeNameService.setColor(java.awt.Color.pink); placeNameService.setMinDisplayDistance(0d); placeNameService.setMaxDisplayDistance(LEVEL_O); placeNameServiceSet.addService(placeNameService, false); } return placeNameServiceSet; } ```