├── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
├── cursor
│ └── modifier
│ │ ├── magic-wand-add.svg
│ │ ├── magic-wand-sam.svg
│ │ ├── magic-wand-subs.svg
│ │ └── magic-wand.svg
├── dialogs
│ ├── auto-sam.svg
│ ├── magic-wand-encode.svg
│ ├── magicwand-info.svg
│ └── magicwand.svg
└── mapmode
│ ├── magic-wand-add.svg
│ ├── magic-wand-merge.svg
│ ├── magic-wand-sam.svg
│ ├── magic-wand-simplify.svg
│ ├── magic-wand-subs.svg
│ └── magic-wand.svg
├── settings.gradle.kts
└── src
└── org
└── openstreetmap
└── josm
└── plugins
└── devseed
└── JosmMagicWand
├── Actions
├── MagicWandAction.java
├── MergeSelectAction.java
├── SamDecodeAction.java
└── SimplifySelectAction.java
├── MainJosmMagicWandPlugin.java
├── ToolSettings.java
├── Ui
├── ButtonActions
│ ├── AutoAddTagAction.java
│ ├── AutoSam.java
│ └── SamEncondeAction.java
├── MagicWandDialog.java
└── TagsDialog.java
└── utils
├── CommonUtils.java
├── Constants.java
├── CustomPolygon.java
├── FloodFillFacade.java
├── ImagePanel.java
├── ImagePanelListener.java
├── ImageSamPanelListener.java
├── LayerImageValues.java
├── NumericField.java
├── SamImage.java
├── SamImageGrid.java
└── samDto
├── DecodeRequestBody.java
├── EncodeResponse.java
└── EncondeRequestBody.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**/build/
5 | !**/src/test/**/build/
6 |
7 | ### IntelliJ IDEA ###
8 | .idea/
9 | *.iws
10 | *.iml
11 | *.ipr
12 | out/
13 | !**/src/main/**/out/
14 | !**/src/test/**/out/
15 |
16 | ### Eclipse ###
17 | .apt_generated
18 | .classpath
19 | .factorypath
20 | .project
21 | .settings
22 | .springBeans
23 | .sts4-cache
24 | bin/
25 | !**/src/main/**/bin/
26 | !**/src/test/**/bin/
27 |
28 | ### NetBeans ###
29 | /nbproject/private/
30 | /nbbuild/
31 | /dist/
32 | /nbdist/
33 | /.nb-gradle/
34 |
35 | ### VS Code ###
36 | .vscode/
37 |
38 | ### Mac OS ###
39 | .DS_Store
40 | .classname
41 |
42 | ### Other ###
43 | osmjar/
44 |
45 | *.env
46 | ### constants
47 | ./src/**/utils/Constants.java
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Development Seed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DS-annotate plugin for Java OpenStreetMap Editor
2 |
3 | The DS-annotate plugin is an extension for the Java OpenStreetMap Desktop Editor (JOSM). Built upon ds-annotate, this plugin utilizes the [Segment Anything Service](https://github.com/developmentseed/segment-anything-services), which leverages Generative AI. Additionally, it allows users to label areas using a spectrum of colors, similar to a magic wand tool, enabling faster and more accurate mapping.
4 |
5 | 
6 |
7 | ## Installation
8 |
9 | 1. Search the magic wand plugin.
10 |
11 | 
12 |
13 | 2. Wait to download the plugin, sometimes it takes a few minutes, because the plugin is 100 MB in size.
14 |
15 | 
16 |
17 | 3. Confirmation window.
18 |
19 | 
20 | 
21 |
22 | ## Usage
23 |
24 | The JOSM Magic Wand plugin offers three functionalities:
25 |
26 | - Generate Geometries
27 | - Merge Geometries
28 | - Simplify Geometries
29 |
30 | ### Generate geometries.
31 |
32 | To generate geometries, you must have a base map activated and a data layer.
33 |
34 | - You can press the shortcut `Ctrl + 1` or select directly in the mode bar (upper
35 | left) ,
36 | you will enter Magic Wand mode and you will see a wand on the
37 | cursor 
38 | .
39 | - Click on the area.
40 | - `ctrl + 2` to generate the geometry.
41 |
42 | - To add or enhance the selection, you can press the `ctrl` button and `click` on new area.
43 | - To subtract the selection, you can press the `switch` button and `click` on area.
44 |
45 | ### Merge geometries
46 |
47 | This functionality allows you to merge several geometries into one, the geometries must intersects.
48 |
49 | 
50 |
51 | - Select one or more geometries.
52 | - Press `ctrl + 3`.
53 |
54 | ### Simplify geometries.
55 |
56 | This functionality allows you to simplify and smooth a geometry.
57 |
58 | - Select one or more geometries.
59 | - Press `ctrl + 4`.
60 |
61 |
62 | ## Requirements
63 |
64 | - Java JDK 11+.
65 | - JOSM 18193 or higher.
66 |
67 | ## Extra options
68 |
69 | 
70 |
71 | 
72 | 1. Select mode.
73 | 2. Open window.
74 | 3. In the window, you will find the following options:
75 |
76 | - **Tolerance**: This option allows you to configure the color tolerance of the Magic Wand tool.
77 |
78 | ```
79 | Higher values expand the tolerance to more colors.
80 | Lower values make the tool more specific to colors.
81 | ```
82 | - **Exterior contour**: This algorithm is specifically designed to simplify polygons while maintaining the shape and outer contour (hull) of the original polygon.
83 |
84 | ```
85 | Higher values result in less simplification.
86 | Lower values result in more simplification.
87 | ```
88 | - **Vertices**: This algorithm focuses on the general simplification of polygons. Its goal is to reduce the number of vertices in a geometry while preserving its overall shape.
89 |
90 | ```
91 | Higher values result in more simplification.
92 | Lower values result in less simplification.
93 | ```
94 | - **Topology**: This algorithm is used to simplify geometries while preserving their topology. Topology refers to the spatial relationship and connectivity between geometric elements.
95 |
96 | ```
97 | Higher values result in more simplification.
98 | Lower values result in less simplification.
99 | ```
100 | - **Smooth Angle**: This option allows you to smooth very sharp angles. The value entered represents the minimum angle to be simplified.
101 | - **add tag**: a pop-up window will appear, allowing you to enter the tag that will be added when generating or simplifying the geometry, the format its `key=value`.
102 |
103 |
104 | To disable the algorithms, set the value to 0.
105 |
106 | ## Use cases
107 | ### Cases where it works well
108 |
109 | | Image | Description |
110 | |------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
111 | |  | The edge of the lake has borders marked with the path. |
112 | |  | The edge of the lake and the farm have marked borders. |
113 | |  | Uniform color and sharp edges (contrast). |
114 | |  | Uniform color and sharp edges (contrast). |
115 | |  | Uniform color and sharp edges (contrast). |
116 | |  | Uniform color and sharp edges (contrast). |
117 |
118 |
119 |
120 | ### Cases where it doesn't work well
121 |
122 | | Image | Description |
123 | |------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
124 | |  | The two farms are separated by a very thin path of similar color. |
125 | |  | Parts of the farm and the border have similar colors with the rest. |
126 | |  | The borders of the farm with the road and the other farm have similar colors. |
127 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import java.net.URL
2 |
3 | plugins {
4 | id("com.github.ben-manes.versions") version "0.39.0"
5 | id("org.openstreetmap.josm") version "0.8.0"
6 | id("java")
7 | id("java-library")
8 | }
9 |
10 | group = "org.openstreetmap.josm.plugins.devseed.JosmMagicWand"
11 | version = "3.0.0"
12 |
13 | java {
14 | toolchain {
15 | languageVersion.set(JavaLanguageVersion.of(17))
16 | }
17 | }
18 |
19 | tasks.jar {
20 | duplicatesStrategy = DuplicatesStrategy.INCLUDE
21 | }
22 | // Repositories Configuration
23 | repositories {
24 | mavenLocal()
25 | mavenCentral()
26 | }
27 |
28 | // Source Sets Configuration
29 | sourceSets {
30 | main {
31 | java {
32 | srcDir("src")
33 | include("org/openstreetmap/**")
34 | }
35 | resources {
36 | srcDir(project.projectDir).include("images/**")
37 | }
38 | }
39 | }
40 |
41 | configurations {
42 | create("externalLibs")
43 | }
44 |
45 | dependencies {
46 | // Libraries to be packed into the JAR
47 | packIntoJar("org.locationtech.jts:jts-core:1.19.0")
48 | packIntoJar("org.locationtech.jts.io:jts-io-common:1.19.0")
49 | packIntoJar("org.openpnp:opencv:4.7.0-0")
50 | packIntoJar("com.fasterxml.jackson.core:jackson-databind:2.15.2")
51 | packIntoJar("com.squareup.okhttp3:okhttp:4.10.0")
52 | }
53 |
54 | josm {
55 | pluginName = "josm_magic_wand"
56 | debugPort = 1729
57 | josmCompileVersion = "19230"
58 | manifest {
59 | description = "JOSM plugin for select areas by color range."
60 | mainClass = "org.openstreetmap.josm.plugins.devseed.JosmMagicWand.MainJosmMagicWandPlugin"
61 | minJosmVersion = "19067"
62 | author = "yunica"
63 | canLoadAtRuntime = true
64 | iconPath = "images/dialogs/magicwand.svg"
65 | website = URL("https://github.com/developmentseed/JosmMagicWand")
66 | minJavaVersion = 17
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/developmentseed/JosmMagicWand/0ecfd62f5cc9c06c1246cfd696a4271cb44ccc3e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/images/cursor/modifier/magic-wand-add.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
93 |
--------------------------------------------------------------------------------
/images/cursor/modifier/magic-wand-sam.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
100 |
--------------------------------------------------------------------------------
/images/cursor/modifier/magic-wand-subs.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
86 |
--------------------------------------------------------------------------------
/images/cursor/modifier/magic-wand.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/images/dialogs/auto-sam.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/dialogs/magic-wand-encode.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/dialogs/magicwand-info.svg:
--------------------------------------------------------------------------------
1 |
2 |
114 |
--------------------------------------------------------------------------------
/images/dialogs/magicwand.svg:
--------------------------------------------------------------------------------
1 |
2 |
51 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand-add.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
93 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand-merge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
94 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand-sam.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
100 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand-simplify.svg:
--------------------------------------------------------------------------------
1 |
2 |
163 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand-subs.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
86 |
--------------------------------------------------------------------------------
/images/mapmode/magic-wand.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "JosmMagicWand"
2 |
3 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Actions/MagicWandAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions;
2 |
3 | import org.locationtech.jts.geom.Geometry;
4 | import org.opencv.core.Mat;
5 | import org.opencv.core.MatOfPoint;
6 | import org.openstreetmap.josm.actions.mapmode.MapMode;
7 | import org.openstreetmap.josm.command.Command;
8 | import org.openstreetmap.josm.command.SequenceCommand;
9 | import org.openstreetmap.josm.data.Bounds;
10 | import org.openstreetmap.josm.data.UndoRedoHandler;
11 | import org.openstreetmap.josm.data.osm.DataSet;
12 | import org.openstreetmap.josm.data.preferences.NamedColorProperty;
13 | import org.openstreetmap.josm.gui.MainApplication;
14 | import org.openstreetmap.josm.gui.MapFrame;
15 | import org.openstreetmap.josm.gui.MapView;
16 | import org.openstreetmap.josm.gui.Notification;
17 | import org.openstreetmap.josm.gui.layer.Layer;
18 | import org.openstreetmap.josm.gui.layer.MapViewPaintable;
19 | import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
20 | import org.openstreetmap.josm.gui.util.ModifierExListener;
21 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
22 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
23 | import org.openstreetmap.josm.spi.preferences.Config;
24 | import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
25 | import org.openstreetmap.josm.tools.ImageProvider;
26 | import org.openstreetmap.josm.tools.Logging;
27 | import org.openstreetmap.josm.tools.Shortcut;
28 |
29 | import javax.swing.*;
30 | import java.awt.*;
31 | import java.awt.event.KeyEvent;
32 | import java.awt.event.MouseEvent;
33 | import java.awt.event.MouseWheelEvent;
34 | import java.awt.event.MouseWheelListener;
35 | import java.awt.image.BufferedImage;
36 | import java.util.Arrays;
37 | import java.util.Collection;
38 | import java.util.List;
39 | import java.util.stream.Collectors;
40 |
41 | import static org.openstreetmap.josm.tools.I18n.marktr;
42 | import static org.openstreetmap.josm.tools.I18n.tr;
43 |
44 | public class MagicWandAction extends MapMode implements MapViewPaintable, KeyPressReleaseListener, ModifierExListener, MouseWheelListener {
45 |
46 | private static final Cursor CURSOR_CUSTOM = ImageProvider.getCursor("crosshair", "magic-wand");
47 | private static final Cursor CURSOR_ADD = ImageProvider.getCursor("crosshair", "magic-wand-add");
48 | private static final Cursor CURSOR_SUBS = ImageProvider.getCursor("crosshair", "magic-wand-subs");
49 | // OPEN CV
50 | private static Mat mat_mask;
51 | private static Mat mat_image;
52 | private final PreferenceChangedListener shapeChangeListener = event -> updCursor();
53 | private Mode mode = Mode.None;
54 | private Mode nextMode = Mode.None;
55 | private Color selectedColor = Color.red;
56 | private Point drawStartPos;
57 | private Point mousePos;
58 |
59 | public MagicWandAction() {
60 | super(tr("Magic Wand"), "magic-wand", tr("Magic wand"), Shortcut.registerShortcut("mapmode:magicwandadd", tr("Mode: {0}", tr("Magic wand add")), KeyEvent.VK_1, Shortcut.CTRL), ImageProvider.getCursor("crosshair", null));
61 |
62 | }
63 |
64 | private Cursor getCursor() {
65 | try {
66 | if (ctrl) {
67 | return CURSOR_ADD;
68 | }
69 | if (shift) {
70 | return CURSOR_SUBS;
71 | }
72 | return CURSOR_CUSTOM;
73 | } catch (Exception e) {
74 | Logging.error(e);
75 | }
76 | return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
77 | }
78 |
79 | private void setCursor(final Cursor c) {
80 | MainApplication.getMap().mapView.setNewCursor(c, this);
81 | }
82 |
83 | @Override
84 | public void enterMode() {
85 | super.enterMode();
86 |
87 | MapFrame map = MainApplication.getMap();
88 | selectedColor = new NamedColorProperty(marktr("selected"), selectedColor).get();
89 | map.mapView.addMouseListener(this);
90 | map.mapView.addMouseMotionListener(this);
91 | map.mapView.addTemporaryLayer(this);
92 | map.mapView.addMouseWheelListener(this);
93 | map.keyDetector.addKeyListener(this);
94 | map.keyDetector.addModifierExListener(this);
95 | Config.getPref().addKeyPreferenceChangeListener("magic_wand_tool.shape", shapeChangeListener);
96 |
97 | updCursor();
98 |
99 | }
100 |
101 | @Override
102 | public void exitMode() {
103 | super.exitMode();
104 | MapFrame map = MainApplication.getMap();
105 | map.mapView.removeMouseListener(this);
106 | map.mapView.removeMouseMotionListener(this);
107 | map.mapView.removeTemporaryLayer(this);
108 | map.mapView.removeMouseWheelListener(this);
109 | map.keyDetector.removeKeyListener(this);
110 | map.keyDetector.removeModifierExListener(this);
111 | Config.getPref().removeKeyPreferenceChangeListener("magic_wand_tool.shape", shapeChangeListener);
112 | cleanMasks();
113 | if (mode != Mode.None) map.mapView.repaint();
114 | mode = Mode.None;
115 | }
116 |
117 | public final void cancelDrawing() {
118 | mode = Mode.None;
119 | MapFrame map = MainApplication.getMap();
120 | if (map == null || map.mapView == null) return;
121 | map.statusLine.setHeading(-1);
122 | map.statusLine.setAngle(-1);
123 | map.mapView.repaint();
124 | updateStatusLine();
125 | }
126 |
127 | @Override
128 | public void modifiersExChanged(int modifiers) {
129 | boolean oldCtrl = ctrl;
130 | boolean oldShift = shift;
131 | updateKeyModifiersEx(modifiers);
132 | if (ctrl != oldCtrl || shift != oldShift) {
133 | processMouseEvent(null);
134 | updCursor();
135 | if (mode != Mode.None) MainApplication.getMap().mapView.repaint();
136 | }
137 | }
138 |
139 | @Override
140 | public void doKeyPressed(KeyEvent e) {
141 | if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
142 | if (mode != Mode.None) e.consume();
143 | cancelDrawing();
144 | }
145 | if ((e.getKeyCode() == KeyEvent.VK_2) && ctrl) {
146 | try {
147 | drawContours();
148 | new Notification(tr("Mapping completed successfully.")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
149 | } catch (Exception ex) {
150 | Logging.error(ex);
151 | cleanMasks();
152 | new Notification(tr("Error create ways.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
153 | }
154 | }
155 | }
156 |
157 | @Override
158 | public void doKeyReleased(KeyEvent e) {
159 | }
160 |
161 | private void processMouseEvent(MouseEvent e) {
162 | if (e != null) {
163 | mousePos = e.getPoint();
164 | updateKeyModifiers(e);
165 |
166 | }
167 | if (mode == Mode.None) {
168 | nextMode = Mode.None;
169 | return;
170 | }
171 | if (mode != Mode.Drawing) {
172 | new Notification(tr("Invalid drawing mode.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
173 | } else {
174 | nextMode = Mode.Drawing;
175 | }
176 | }
177 |
178 | @Override
179 | public void mouseWheelMoved(MouseWheelEvent e) {
180 | cleanMasks();
181 | }
182 |
183 | @Override
184 | public void paint(Graphics2D g, MapView mv, Bounds bbox) {
185 | if (mat_mask != null && mat_image != null) {
186 | try {
187 | Mat new_mask = CommonUtils.maskInsideImage(mat_image, mat_mask, 0.45);
188 | BufferedImage bi_mask = CommonUtils.toBufferedImage(new_mask);
189 | g.drawImage(bi_mask, 0, 0, null);
190 | } catch (Exception e) {
191 | Logging.error(e);
192 | }
193 | }
194 | if (mode == Mode.None) {
195 | return;
196 | }
197 |
198 | g.setColor(selectedColor);
199 | g.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
200 | g.setStroke(new BasicStroke(1));
201 | }
202 |
203 | private void drawingStart(MouseEvent e) {
204 | mousePos = e.getPoint();
205 | drawStartPos = mousePos;
206 | mode = Mode.Drawing;
207 | updateStatusLine();
208 | }
209 |
210 | @Override
211 | public void mousePressed(MouseEvent e) {
212 | Logging.info("-------- mousePressed -----------");
213 | if (e.getButton() != MouseEvent.BUTTON1) return;
214 | if (!MainApplication.getMap().mapView.isActiveLayerDrawable()) return;
215 | requestFocusInMapView();
216 | if (mode == Mode.None) drawingStart(e);
217 | }
218 |
219 | @Override
220 | public void mouseDragged(MouseEvent e) {
221 | Logging.info("-------- mouseDragged -----------");
222 | if (e.getButton() == MouseEvent.BUTTON1) return;
223 |
224 | processMouseEvent(e);
225 | updCursor();
226 | cleanMasks();
227 | MainApplication.getMap().mapView.repaint();
228 | }
229 |
230 | @Override
231 | public void mouseReleased(MouseEvent e) {
232 | Logging.info("-------- mouseReleased -----------");
233 | if (e.getButton() != MouseEvent.BUTTON1) return;
234 | if (!MainApplication.getMap().mapView.isActiveLayerDrawable()) return;
235 | try {
236 | drawingFinish(e);
237 | } catch (Exception ex) {
238 | Logging.error(ex);
239 | }
240 | }
241 |
242 | private void drawingFinish(MouseEvent e) throws Exception {
243 |
244 | if (mat_image == null) {
245 | mat_image = CommonUtils.bufferedImage2Mat(getLayeredImage());
246 | }
247 |
248 | Logging.info("-------- drawingFinish -----------");
249 | mat_mask = CommonUtils.processImage(mat_image, mat_mask, ctrl, shift, e.getX(), e.getY());
250 | MainApplication.getMap().repaint();
251 | }
252 |
253 | private void updCursor() {
254 | if (!MainApplication.isDisplayingMapView()) return;
255 | setCursor(getCursor());
256 | }
257 |
258 | @Override
259 | public boolean layerIsSupported(Layer l) {
260 | return isEditableDataLayer(l);
261 | }
262 |
263 | private BufferedImage getLayeredImage() {
264 | MapView mapView = MainApplication.getMap().mapView;
265 |
266 | BufferedImage bufImage = new BufferedImage(mapView.getWidth(), mapView.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
267 | Graphics2D imgGraphics = bufImage.createGraphics();
268 | imgGraphics.setClip(0, 0, mapView.getWidth(), mapView.getHeight());
269 |
270 | for (Layer layer : mapView.getLayerManager().getVisibleLayersInZOrder()) {
271 | if (layer.isVisible() && layer.isBackgroundLayer()) {
272 | Composite translucent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) layer.getOpacity());
273 | imgGraphics.setComposite(translucent);
274 | mapView.paintLayer(layer, imgGraphics);
275 | }
276 | }
277 |
278 | return bufImage;
279 | }
280 |
281 | private void drawContours() throws Exception {
282 | if (mat_mask == null) {
283 | new Notification(tr("No have mask ")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
284 | return;
285 | }
286 | if (mat_mask.empty()) {
287 | new Notification(tr("Mask empty, select again")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
288 | return;
289 | }
290 | MapView mapview = MainApplication.getMap().mapView;
291 | List contourns = CommonUtils.obtainContour(mat_mask);
292 | List geometries = CommonUtils.contourn2Geometry(contourns, mapview);
293 | if (geometries.isEmpty()) return;
294 | DataSet ds = MainApplication.getLayerManager().getEditDataSet();
295 | // simplify
296 | List geometriesSimplify = geometries.stream().map(CommonUtils::simplifySmoothGeometry).collect(Collectors.toList());
297 | if (geometriesSimplify.isEmpty()) return;
298 | String tagKey = "";
299 | String tagValue = "";
300 | if (ToolSettings.getAutoTags() != null && !ToolSettings.getAutoTags().isEmpty()) {
301 | List strings = Arrays.asList(ToolSettings.getAutoTags().split("="));
302 | if (strings.size() > 1) {
303 | tagKey = strings.get(0);
304 | tagValue = strings.get(1);
305 | }
306 | }
307 |
308 | Collection cmds = CommonUtils.geometry2WayCommands(ds, geometriesSimplify, tagKey, tagValue);
309 | UndoRedoHandler.getInstance().add(new SequenceCommand(tr("draw merge way"), cmds));
310 | cleanMasks();
311 | mapview.repaint();
312 | }
313 |
314 | private void cleanMasks() {
315 | mat_mask = null;
316 | mat_image = null;
317 | }
318 |
319 | private enum Mode {
320 | None, Drawing
321 | }
322 | }
323 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Actions/MergeSelectAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions;
2 |
3 | import org.locationtech.jts.geom.Geometry;
4 | import org.openstreetmap.josm.actions.JosmAction;
5 | import org.openstreetmap.josm.command.Command;
6 | import org.openstreetmap.josm.command.SequenceCommand;
7 | import org.openstreetmap.josm.data.UndoRedoHandler;
8 | import org.openstreetmap.josm.data.osm.DataSelectionListener;
9 | import org.openstreetmap.josm.data.osm.DataSet;
10 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
11 | import org.openstreetmap.josm.data.osm.Way;
12 | import org.openstreetmap.josm.gui.MainApplication;
13 | import org.openstreetmap.josm.gui.MapFrame;
14 | import org.openstreetmap.josm.gui.Notification;
15 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
16 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
17 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CustomPolygon;
18 | import org.openstreetmap.josm.tools.Logging;
19 | import org.openstreetmap.josm.tools.Shortcut;
20 |
21 | import javax.swing.*;
22 | import java.awt.event.ActionEvent;
23 | import java.awt.event.KeyEvent;
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.Collection;
27 | import java.util.List;
28 |
29 | import static org.openstreetmap.josm.tools.I18n.tr;
30 |
31 | public class MergeSelectAction extends JosmAction implements DataSelectionListener {
32 |
33 |
34 | public MergeSelectAction(String text) {
35 | super(tr(text), "mapmode/magic-wand-merge", tr("merge multiple geometries into one"), Shortcut.registerShortcut("data:magicwandmerge", tr("Data: {0}", tr("merge multiple geometries into one")), KeyEvent.VK_3, Shortcut.CTRL), true);
36 | }
37 |
38 | @Override
39 | public void actionPerformed(ActionEvent actionEvent) {
40 | if (!isEnabled()) return;
41 | Collection selWays = getSelectedWays();
42 | if (selWays.isEmpty()) {
43 | new Notification(tr("No ways selected.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
44 | return;
45 | }
46 |
47 | List geometryMerge;
48 | try {
49 | geometryMerge = mergeWays(selWays);
50 | } catch (Exception e) {
51 | new Notification(tr("Incorrect geometry.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
52 | return;
53 | }
54 | if (geometryMerge.isEmpty()) {
55 | new Notification(tr("Does not have merged ways.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
56 | return;
57 | }
58 | boolean hasDraw = drawWays(geometryMerge);
59 | if (hasDraw) {
60 | removeSelected(actionEvent);
61 | }
62 |
63 | }
64 |
65 | @Override
66 | public void selectionChanged(SelectionChangeEvent event) {
67 | updateEnabledStateOnCurrentSelection();
68 | }
69 |
70 | @Override
71 | protected void updateEnabledState(Collection extends OsmPrimitive> selection) {
72 | updateEnabledStateOnModifiableSelection(selection);
73 | }
74 |
75 | private Collection getSelectedWays() {
76 | return getLayerManager().getEditDataSet().getSelectedWays();
77 | }
78 |
79 | private List mergeWays(Collection ways) throws Exception {
80 | List polygons = new ArrayList<>();
81 | for (Way w : ways) {
82 | CustomPolygon cp = new CustomPolygon();
83 | cp.fromWay(w);
84 | polygons.add(cp);
85 | }
86 | return CommonUtils.mergeGeometry(polygons);
87 | }
88 |
89 | private boolean drawWays(List geometries) {
90 | if (geometries.isEmpty()) return false;
91 | DataSet ds = MainApplication.getLayerManager().getEditDataSet();
92 |
93 | try {
94 | String tagKey = "";
95 | String tagValue = "";
96 | if (ToolSettings.getAutoTags() != null && !ToolSettings.getAutoTags().isEmpty()) {
97 | List strings = Arrays.asList(ToolSettings.getAutoTags().split("="));
98 | if (strings.size() > 1) {
99 | tagKey = strings.get(0);
100 | tagValue = strings.get(1);
101 | }
102 | }
103 | Collection cmds = CommonUtils.geometry2WayCommands(ds, geometries, tagKey, tagValue);
104 | UndoRedoHandler.getInstance().add(new SequenceCommand(tr("draw merge way"), cmds));
105 | return !cmds.isEmpty();
106 | } catch (Exception e) {
107 | Logging.error(e);
108 | return false;
109 | }
110 | }
111 |
112 | private void removeSelected(ActionEvent e) {
113 | MapFrame map = MainApplication.getMap();
114 | if (!isEnabled() || !map.mapView.isActiveLayerVisible()) {
115 | return;
116 | }
117 | map.mapModeDelete.doActionPerformed(e);
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Actions/SamDecodeAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions;
2 |
3 | import org.openstreetmap.josm.actions.mapmode.MapMode;
4 | import org.openstreetmap.josm.data.coor.EastNorth;
5 | import org.openstreetmap.josm.data.coor.LatLon;
6 | import org.openstreetmap.josm.data.osm.DataSet;
7 | import org.openstreetmap.josm.data.projection.Projection;
8 | import org.openstreetmap.josm.data.projection.Projections;
9 | import org.openstreetmap.josm.gui.MainApplication;
10 | import org.openstreetmap.josm.gui.MapFrame;
11 | import org.openstreetmap.josm.gui.MapView;
12 | import org.openstreetmap.josm.gui.Notification;
13 | import org.openstreetmap.josm.gui.layer.OsmDataLayer;
14 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
15 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
16 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.ImageSamPanelListener;
17 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.SamImage;
18 | import org.openstreetmap.josm.tools.ImageProvider;
19 | import org.openstreetmap.josm.tools.Logging;
20 |
21 | import javax.swing.*;
22 | import java.awt.*;
23 | import java.awt.event.MouseEvent;
24 | import java.awt.event.MouseListener;
25 |
26 | import static org.openstreetmap.josm.tools.I18n.tr;
27 |
28 | public class SamDecodeAction extends MapMode implements MouseListener {
29 | private static final Cursor CURSOR_CUSTOM = ImageProvider.getCursor("crosshair", "magic-wand-sam");
30 | private Mode mode = Mode.None;
31 | private final Mode nextMode = Mode.None;
32 | private Point drawStartPos;
33 | private Point mousePos;
34 | private final ImageSamPanelListener listener;
35 |
36 | public SamDecodeAction(ImageSamPanelListener listener) {
37 | super(tr("Magic Wand SAM"), "magic-wand-sam", tr("Magic Wand SAM action"), null, ImageProvider.getCursor("crosshair", null));
38 | this.listener = listener;
39 | }
40 |
41 | private Cursor getCursor() {
42 | return CURSOR_CUSTOM;
43 | }
44 |
45 | private void setCursor(final Cursor c) {
46 | MainApplication.getMap().mapView.setNewCursor(c, this);
47 | }
48 |
49 | private void updCursor() {
50 | if (!MainApplication.isDisplayingMapView()) return;
51 | setCursor(getCursor());
52 | }
53 |
54 | @Override
55 | public void enterMode() {
56 | super.enterMode();
57 |
58 | MapFrame map = MainApplication.getMap();
59 | map.mapView.addMouseListener(this);
60 | map.mapView.addMouseMotionListener(this);
61 |
62 | updCursor();
63 |
64 | }
65 |
66 | @Override
67 | public void exitMode() {
68 | super.exitMode();
69 | MapFrame map = MainApplication.getMap();
70 | map.mapView.removeMouseListener(this);
71 | map.mapView.removeMouseMotionListener(this);
72 | if (mode != Mode.None) map.mapView.repaint();
73 | mode = Mode.None;
74 | }
75 |
76 | public final void cancelDrawing() {
77 | mode = Mode.None;
78 | MapFrame map = MainApplication.getMap();
79 | if (map == null || map.mapView == null) return;
80 | map.statusLine.setHeading(-1);
81 | map.statusLine.setAngle(-1);
82 | map.mapView.repaint();
83 | updateStatusLine();
84 | }
85 |
86 | private void drawingStart(MouseEvent e) {
87 | mousePos = e.getPoint();
88 | drawStartPos = mousePos;
89 | mode = Mode.Drawing;
90 | updateStatusLine();
91 | }
92 |
93 | @Override
94 | public void mouseReleased(MouseEvent event) {
95 | Logging.info("-------- mouseReleased -----------");
96 | if (event.getButton() != MouseEvent.BUTTON1) return;
97 | if (!MainApplication.getMap().mapView.isActiveLayerDrawable()) return;
98 |
99 | checkApi(event.getX(), event.getY());
100 | }
101 |
102 | private void checkApi(int x, int y) {
103 | Thread apiThread = new Thread(() -> {
104 | String device = CommonUtils.serverSamLive();
105 | SwingUtilities.invokeLater(() -> {
106 | if (!device.isEmpty()) {
107 | Logging.info("Server is online: " + device);
108 | apiThreadDecode(x, y);
109 | } else {
110 | Logging.error("Server is down");
111 | new Notification(tr("SAM server not reachable.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
112 | }
113 | });
114 | });
115 | apiThread.start();
116 | }
117 |
118 | private void apiThreadDecode(int x, int y) {
119 | Thread aoiThread = new Thread(() -> {
120 | drawWays(x, y);
121 | SwingUtilities.invokeLater(() -> {
122 | Logging.error("later");
123 | });
124 | });
125 | aoiThread.start();
126 | }
127 |
128 |
129 | private void drawWays(int x, int y) {
130 | try {
131 |
132 | OsmDataLayer dataActiveLayer = CommonUtils.getActiveDataLayerNameOrCreate("Data Layer new");
133 |
134 | MapView mapView = MainApplication.getMap().mapView;
135 | DataSet ds = MainApplication.getLayerManager().getEditDataSet();
136 |
137 | String tagKey = "";
138 | String tagValue = "";
139 |
140 | LatLon latLon = mapView.getLatLon(x, y);
141 | Projection currentProjection = mapView.getProjection();
142 | EastNorth eastNorth = latLon.getEastNorth(currentProjection);
143 |
144 | SamImage samImage = listener.getSamImageIncludepoint(eastNorth.getX(), eastNorth.getY());
145 | if (samImage == null) {
146 | new Notification(tr("Click inside of active AOI to enable Segment Anything Model.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
147 | return;
148 | }
149 | Projection epsg4326 = Projections.getProjectionByCode("EPSG:4326");
150 | EastNorth eastNort4326 = epsg4326.latlon2eastNorth(latLon);
151 |
152 |
153 | OsmDataLayer newLayerSam = samImage.fetchDecodePoint(eastNort4326.getX(), eastNort4326.getY());
154 | if (newLayerSam == null) {
155 | new Notification(tr("Error fetch data.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
156 | return;
157 | }
158 | CommonUtils.pasteDataFromLayerByName(dataActiveLayer, newLayerSam);
159 | } catch (Exception e) {
160 | Logging.error(e);
161 | new Notification(tr("Error data generation.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
162 | }
163 | }
164 |
165 | private enum Mode {
166 | None, Drawing
167 | }
168 |
169 |
170 | }
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Actions/SimplifySelectAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions;
2 |
3 | import org.locationtech.jts.geom.Coordinate;
4 | import org.locationtech.jts.geom.Geometry;
5 | import org.openstreetmap.josm.actions.JosmAction;
6 | import org.openstreetmap.josm.command.Command;
7 | import org.openstreetmap.josm.command.SequenceCommand;
8 | import org.openstreetmap.josm.data.UndoRedoHandler;
9 | import org.openstreetmap.josm.data.osm.DataSelectionListener;
10 | import org.openstreetmap.josm.data.osm.DataSet;
11 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
12 | import org.openstreetmap.josm.data.osm.Way;
13 | import org.openstreetmap.josm.gui.MainApplication;
14 | import org.openstreetmap.josm.gui.MapFrame;
15 | import org.openstreetmap.josm.gui.Notification;
16 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
17 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
18 | import org.openstreetmap.josm.tools.Logging;
19 | import org.openstreetmap.josm.tools.Shortcut;
20 |
21 | import javax.swing.*;
22 | import java.awt.event.ActionEvent;
23 | import java.awt.event.KeyEvent;
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.Collection;
27 | import java.util.List;
28 |
29 | import static org.openstreetmap.josm.tools.I18n.tr;
30 |
31 | public class SimplifySelectAction extends JosmAction implements DataSelectionListener {
32 |
33 |
34 | public SimplifySelectAction(String text) {
35 | super(tr(text), "mapmode/magic-wand-simplify", tr("Simplify multiple geometries"), Shortcut.registerShortcut("data:magicwandsimplify", tr("Data: {0}", tr("Simplify multiple geometries")), KeyEvent.VK_4, Shortcut.CTRL), true);
36 | }
37 |
38 | @Override
39 | public void actionPerformed(ActionEvent actionEvent) {
40 | if (!isEnabled()) return;
41 | Collection selWays = getSelectedWays();
42 | if (selWays.isEmpty()) {
43 | new Notification(tr("No ways selected.")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
44 | return;
45 | }
46 |
47 | try {
48 | List geometrySimplify = simplifyWays(selWays);
49 | boolean hasDraw = drawWays(geometrySimplify);
50 | if (hasDraw) {
51 | removeSelected(actionEvent);
52 | }
53 | } catch (Exception e) {
54 | Logging.error(e);
55 | }
56 |
57 | }
58 |
59 | @Override
60 | public void selectionChanged(SelectionChangeEvent event) {
61 | updateEnabledStateOnCurrentSelection();
62 | }
63 |
64 | @Override
65 | protected void updateEnabledState(Collection extends OsmPrimitive> selection) {
66 | updateEnabledStateOnModifiableSelection(selection);
67 | }
68 |
69 | private Collection getSelectedWays() {
70 | return getLayerManager().getEditDataSet().getSelectedWays();
71 | }
72 |
73 | private List simplifyWays(Collection ways) throws Exception {
74 | List geometries = new ArrayList<>();
75 | for (Way w : ways) {
76 | List coordsMercator = CommonUtils.nodes2Coordinates(w.getNodes());
77 | Geometry geometryMercator = CommonUtils.coordinates2Polygon(coordsMercator);
78 | Geometry geometrySimplify = CommonUtils.simplifySmoothGeometry(geometryMercator);
79 | geometries.add(geometrySimplify);
80 | }
81 | return geometries;
82 | }
83 |
84 | private boolean drawWays(List geometrySimplify) {
85 | if (geometrySimplify.isEmpty()) return false;
86 | DataSet ds = MainApplication.getLayerManager().getEditDataSet();
87 | try {
88 | String tagKey = "";
89 | String tagValue = "";
90 | if (ToolSettings.getAutoTags() != null && !ToolSettings.getAutoTags().isEmpty()) {
91 | List strings = Arrays.asList(ToolSettings.getAutoTags().split("="));
92 | if (strings.size() > 1) {
93 | tagKey = strings.get(0);
94 | tagValue = strings.get(1);
95 | }
96 | }
97 | Collection cmds = CommonUtils.geometry2WayCommands(ds, geometrySimplify, tagKey, tagValue);
98 | UndoRedoHandler.getInstance().add(new SequenceCommand(tr("simplify way"), cmds));
99 | return !cmds.isEmpty();
100 | } catch (Exception e) {
101 | Logging.error(e);
102 | return false;
103 | }
104 | }
105 |
106 | private void removeSelected(ActionEvent e) {
107 | MapFrame map = MainApplication.getMap();
108 | if (!isEnabled() || !map.mapView.isActiveLayerVisible()) return;
109 | map.mapModeDelete.doActionPerformed(e);
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/MainJosmMagicWandPlugin.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand;
2 |
3 |
4 | import org.openstreetmap.josm.gui.IconToggleButton;
5 | import org.openstreetmap.josm.gui.MainApplication;
6 | import org.openstreetmap.josm.gui.MainMenu;
7 | import org.openstreetmap.josm.gui.MapFrame;
8 | import org.openstreetmap.josm.plugins.Plugin;
9 | import org.openstreetmap.josm.plugins.PluginInformation;
10 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.MagicWandAction;
11 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.MergeSelectAction;
12 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.SamDecodeAction;
13 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.SimplifySelectAction;
14 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions.AutoAddTagAction;
15 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.MagicWandDialog;
16 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
17 | import org.openstreetmap.josm.tools.Logging;
18 |
19 | import javax.swing.*;
20 |
21 | public class MainJosmMagicWandPlugin extends Plugin {
22 |
23 | public MainJosmMagicWandPlugin(PluginInformation info) {
24 | super(info);
25 | try {
26 | if (Double.parseDouble(System.getProperty("java.specification.version")) >= 12) {
27 | nu.pattern.OpenCV.loadLocally();
28 | } else {
29 | nu.pattern.OpenCV.loadShared();
30 | }
31 | } catch (Exception e) {
32 | Logging.error(e.getMessage());
33 | throw new RuntimeException(e);
34 | }
35 |
36 | JMenu jToolmenu = MainApplication.getMenu().toolsMenu;
37 | jToolmenu.addSeparator();
38 | MainMenu.add(jToolmenu, new MergeSelectAction("Merge way"));
39 | MainMenu.add(jToolmenu, new SimplifySelectAction("Simplify way"));
40 | MainMenu.add(jToolmenu, new AutoAddTagAction("Add default tag"));
41 |
42 | // create a folder
43 | CommonUtils.createCacheDir();
44 | CommonUtils.createCacheSamDir();
45 |
46 | }
47 |
48 | @Override
49 | public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
50 | if (oldFrame == null && newFrame != null) {
51 | MagicWandDialog magicWandDialog = new MagicWandDialog();
52 | newFrame.addToggleDialog(magicWandDialog);
53 | MainApplication.getMap().addMapMode(new IconToggleButton(new MagicWandAction()));
54 | MainApplication.getMap().addMapMode(new IconToggleButton(new SamDecodeAction(magicWandDialog)));
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/ToolSettings.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand;
2 |
3 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.SamImage;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public final class ToolSettings {
9 | private static int tolerance;
10 | private static int maskClose;
11 | private static int maskMedian;
12 | private static int maskOpen;
13 | // simplify
14 | private static double simplDouglasP;
15 | private static double simplPolygonHull;
16 | private static double simplTopologyPreserving;
17 | //smooth
18 | private static double chaikinSmooDistance;
19 | private static double chaikinSmooAngle;
20 | // tags
21 | private static String autoTags;
22 | // sam images
23 | private static int simplAreaSam;
24 | private static double simplDistanceSam;
25 |
26 | private static List samImagesList = new ArrayList<>();
27 | private ToolSettings() {
28 | }
29 |
30 | public static List getSamImagesList() {
31 | return samImagesList;
32 | }
33 |
34 | public static void setSamImagesList(List samImagesList) {
35 | ToolSettings.samImagesList = samImagesList;
36 | }
37 |
38 | public static void setSamImage(SamImage samImage) {
39 | ToolSettings.samImagesList.add(samImage);
40 | }
41 |
42 | public static void clearSamImagesList() {
43 | ToolSettings.samImagesList.clear();
44 | }
45 |
46 | public static int getMaskOpen() {
47 | return maskOpen;
48 | }
49 |
50 | public static void setMaskOpen(int maskOpen) {
51 | ToolSettings.maskOpen = maskOpen;
52 | }
53 |
54 |
55 | public static int getTolerance() {
56 | return tolerance;
57 | }
58 |
59 | public static void setTolerance(int tolerance) {
60 | ToolSettings.tolerance = tolerance;
61 | }
62 |
63 | public static int getMaskClose() {
64 | return maskClose;
65 | }
66 |
67 | public static void setMaskClose(int maskClose) {
68 | ToolSettings.maskClose = maskClose;
69 | }
70 |
71 | public static int getMaskMedian() {
72 | return maskMedian;
73 | }
74 |
75 | public static void setMaskMedian(int maskMedian) {
76 | ToolSettings.maskMedian = maskMedian;
77 | }
78 |
79 | public static double getSimplPolygonHull() {
80 | return simplPolygonHull;
81 | }
82 |
83 | public static void setSimplPolygonHull(double simplPolygonHull) {
84 | ToolSettings.simplPolygonHull = simplPolygonHull;
85 | }
86 |
87 | public static double getSimplTopologyPreserving() {
88 | return simplTopologyPreserving;
89 | }
90 |
91 | public static void setSimplTopologyPreserving(double simplTopologyPreserving) {
92 | ToolSettings.simplTopologyPreserving = simplTopologyPreserving;
93 | }
94 |
95 | public static double getSimplDouglasP() {
96 | return simplDouglasP;
97 | }
98 |
99 | public static void setSimplDouglasP(double simplDouglasP) {
100 | ToolSettings.simplDouglasP = simplDouglasP;
101 | }
102 |
103 | public static double getChaikinSmooAngle() {
104 | return chaikinSmooAngle;
105 | }
106 |
107 | public static void setChaikinSmooAngle(double chaikinSmooAngle) {
108 | ToolSettings.chaikinSmooAngle = chaikinSmooAngle;
109 | }
110 |
111 | public static double getChaikinSmooDistance() {
112 | return chaikinSmooDistance;
113 | }
114 |
115 | public static void setChaikinSmooDistance(double chaikinSmooDistance) {
116 | ToolSettings.chaikinSmooDistance = chaikinSmooDistance;
117 | }
118 |
119 | public static String getAutoTags() {
120 | return ToolSettings.autoTags;
121 | }
122 |
123 | public static void setAutoTags(String autoTags) {
124 | ToolSettings.autoTags = autoTags;
125 | }
126 |
127 | public static int getSimplAreaSam() {
128 | return simplAreaSam;
129 | }
130 |
131 | public static void setSimplAreaSam(int simplAreaSam) {
132 | ToolSettings.simplAreaSam = simplAreaSam;
133 | }
134 |
135 | public static double getSimplDistanceSam() {
136 | return simplDistanceSam;
137 | }
138 |
139 | public static void setSimplDistanceSam(double simplDistanceSam) {
140 | ToolSettings.simplDistanceSam = simplDistanceSam;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Ui/ButtonActions/AutoAddTagAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions;
2 |
3 | import org.openstreetmap.josm.actions.JosmAction;
4 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.TagsDialog;
5 |
6 | import java.awt.event.ActionEvent;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | import static org.openstreetmap.josm.tools.I18n.tr;
10 |
11 | public class AutoAddTagAction extends JosmAction {
12 | AtomicBoolean isPerforming = new AtomicBoolean(false);
13 |
14 | public AutoAddTagAction(String text) {
15 | super(tr(text), "dialogs/add", tr("Add a new key/value tag to geometries"), null, false);
16 | }
17 |
18 | @Override
19 | public void actionPerformed(ActionEvent e) {
20 | if (!/*successful*/isPerforming.compareAndSet(false, true)) {
21 | return;
22 | }
23 | try {
24 | TagsDialog tagsDialog = new TagsDialog();
25 | if (tagsDialog.getValue() != 1) return;
26 | tagsDialog.saveSettings();
27 | } finally {
28 | isPerforming.set(false);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Ui/ButtonActions/AutoSam.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions;
2 |
3 | import org.openstreetmap.josm.actions.JosmAction;
4 | import org.openstreetmap.josm.gui.MainApplication;
5 | import org.openstreetmap.josm.gui.MapView;
6 | import org.openstreetmap.josm.gui.Notification;
7 | import org.openstreetmap.josm.gui.layer.ImageryLayer;
8 | import org.openstreetmap.josm.gui.layer.Layer;
9 | import org.openstreetmap.josm.gui.layer.OsmDataLayer;
10 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
11 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.ImageSamPanelListener;
12 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.LayerImageValues;
13 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.SamImage;
14 | import org.openstreetmap.josm.tools.Logging;
15 |
16 | import javax.swing.*;
17 | import java.awt.*;
18 | import java.awt.event.ActionEvent;
19 | import java.awt.image.BufferedImage;
20 | import java.util.List;
21 |
22 | import static org.openstreetmap.josm.tools.I18n.tr;
23 |
24 | public class AutoSam extends JosmAction {
25 | private final ImageSamPanelListener listener;
26 |
27 | public AutoSam(ImageSamPanelListener listener) {
28 | super(tr("AUTO SAM"), "dialogs/auto-sam", tr("Automatic sam"),
29 | null, false);
30 | this.listener = listener;
31 | }
32 |
33 | @Override
34 | public void actionPerformed(ActionEvent e) {
35 | MapView mapView = MainApplication.getMap().mapView;
36 | // check layers
37 | List targetLayer = MainApplication.getLayerManager().getLayers();
38 | boolean hasMapLayer = false;
39 | for (Layer layer : targetLayer) {
40 | if (layer instanceof ImageryLayer && layer.isVisible()) {
41 | hasMapLayer = true;
42 | break;
43 | }
44 | }
45 |
46 | if (hasMapLayer) {
47 | LayerImageValues layerImageValues = getLayeredImage(mapView);
48 | SamImage samImage = new SamImage(mapView.getProjectionBounds(), mapView.getProjection(), mapView.getScale(), layerImageValues.getBufferedImage(), layerImageValues.getLayerName());
49 | // effect
50 | checkApi(samImage);
51 |
52 | } else {
53 | new Notification(tr("An Map active layer is needed.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
54 | }
55 | }
56 |
57 | private void checkApi(SamImage samImage) {
58 | Thread apiThread = new Thread(() -> {
59 | String device = CommonUtils.serverSamLive();
60 | SwingUtilities.invokeLater(() -> {
61 | if (!device.isEmpty()) {
62 | Logging.info("Server is online: " + device);
63 | apiThreadCreateAoi(samImage);
64 | } else {
65 | Logging.error("Server is down");
66 | new Notification(tr("SAM server not reachable.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
67 | }
68 | });
69 | });
70 | apiThread.start();
71 | }
72 |
73 | private void apiThreadCreateAoi(SamImage samImage) {
74 | OsmDataLayer dataActiveLayer = CommonUtils.getActiveDataLayerNameOrCreate("Data Layer new");
75 | // if (dataActiveLayer.getAssociatedFile() == null || dataActiveLayer.requiresSaveToFile()) {
76 | // new Notification(tr("Save changes to the current Data Layer or associate it with a file.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
77 | // setEnabled(true);
78 | // return;
79 | // }
80 | setEnabled(false);
81 | Thread aoiThread = new Thread(() -> {
82 | try {
83 | new Notification(tr("Creating Aoi...")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
84 | samImage.setEncodeImage();
85 | new Notification(tr("Automatically segmenting ..")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
86 | setEnabled(false);
87 | OsmDataLayer newLayerSam = samImage.autoAnnotateSam();
88 | setEnabled(false);
89 | SwingUtilities.invokeLater(() -> {
90 | if (newLayerSam != null) {
91 | addSamImage(samImage);
92 | CommonUtils.pasteDataFromLayerByName(dataActiveLayer, newLayerSam);
93 | samImage.updateCacheImage();
94 | }
95 | setEnabled(true);
96 | });
97 | } catch (Exception e) {
98 | Logging.error(e);
99 | setEnabled(true);
100 | }
101 | });
102 | aoiThread.start();
103 | }
104 |
105 |
106 | private void addSamImage(SamImage samImage) {
107 | if (samImage.getEncode() && !samImage.getImageUrl().isEmpty()) {
108 | listener.addLayer();
109 | listener.addBboxLayer(samImage.getBboxWay());
110 | listener.onAddSamImage(samImage);
111 | new Notification(tr("Added a sam image.")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
112 | } else {
113 | new Notification(tr("Error adding sam image.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
114 | }
115 | }
116 |
117 | private LayerImageValues getLayeredImage(MapView mapView) {
118 | LayerImageValues layerImageValues = new LayerImageValues();
119 | BufferedImage bufImage = new BufferedImage(mapView.getWidth(), mapView.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
120 | Graphics2D imgGraphics = bufImage.createGraphics();
121 | imgGraphics.setClip(0, 0, mapView.getWidth(), mapView.getHeight());
122 |
123 | for (Layer layer : mapView.getLayerManager().getVisibleLayersInZOrder()) {
124 | if (layer.isVisible() && layer.isBackgroundLayer()) {
125 | Composite translucent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) layer.getOpacity());
126 | imgGraphics.setComposite(translucent);
127 | mapView.paintLayer(layer, imgGraphics);
128 | layerImageValues.setBufferedImage(bufImage);
129 | layerImageValues.setLayerName(layer.getName());
130 | }
131 |
132 | }
133 |
134 | return layerImageValues;
135 | }
136 |
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Ui/ButtonActions/SamEncondeAction.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions;
2 |
3 | import org.openstreetmap.josm.actions.JosmAction;
4 | import org.openstreetmap.josm.gui.MainApplication;
5 | import org.openstreetmap.josm.gui.MapView;
6 | import org.openstreetmap.josm.gui.Notification;
7 | import org.openstreetmap.josm.gui.layer.ImageryLayer;
8 | import org.openstreetmap.josm.gui.layer.Layer;
9 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.CommonUtils;
10 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.ImageSamPanelListener;
11 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.LayerImageValues;
12 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.SamImage;
13 | import org.openstreetmap.josm.tools.Logging;
14 |
15 | import javax.swing.*;
16 | import java.awt.*;
17 | import java.awt.event.ActionEvent;
18 | import java.awt.image.BufferedImage;
19 | import java.util.List;
20 |
21 | import static org.openstreetmap.josm.tools.I18n.tr;
22 |
23 | public class SamEncondeAction extends JosmAction {
24 | private final ImageSamPanelListener listener;
25 |
26 | public SamEncondeAction(ImageSamPanelListener listener) {
27 | super(tr("SAM AOI"), "dialogs/magic-wand-encode", tr("Add a new SAM AOI"), null, false);
28 | this.listener = listener;
29 | }
30 |
31 | @Override
32 | public void actionPerformed(ActionEvent e) {
33 | MapView mapView = MainApplication.getMap().mapView;
34 | // check layers
35 | List targetLayer = MainApplication.getLayerManager().getLayers();
36 | boolean hasMapLayer = false;
37 | for (Layer layer : targetLayer) {
38 | if (layer instanceof ImageryLayer && layer.isVisible()) {
39 | hasMapLayer = true;
40 | break;
41 | }
42 | }
43 |
44 | if (hasMapLayer) {
45 | LayerImageValues layerImageValues = getLayeredImage(mapView);
46 | SamImage samImage = new SamImage(mapView.getProjectionBounds(), mapView.getProjection(), mapView.getScale(), layerImageValues.getBufferedImage(), layerImageValues.getLayerName());
47 |
48 | // effect
49 | setEnabled(false);
50 | checkApi(samImage);
51 |
52 | } else {
53 | new Notification(tr("An active layer is needed.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
54 | }
55 | }
56 |
57 | private void checkApi(SamImage samImage) {
58 | Thread apiThread = new Thread(() -> {
59 | String device = CommonUtils.serverSamLive();
60 | SwingUtilities.invokeLater(() -> {
61 | if (!device.isEmpty()) {
62 | Logging.info("Server is online: " + device);
63 | apiThreadCreateAoi(samImage);
64 | } else {
65 | Logging.error("Server is down");
66 | new Notification(tr("SAM server not reachable.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
67 | }
68 | });
69 | });
70 | apiThread.start();
71 | }
72 |
73 | private void apiThreadCreateAoi(SamImage samImage) {
74 | setEnabled(false);
75 | Thread aoiThread = new Thread(() -> {
76 | samImage.setEncodeImage();
77 | SwingUtilities.invokeLater(() -> {
78 | addSamImage(samImage);
79 | samImage.updateCacheImage();
80 | setEnabled(true);
81 | });
82 | });
83 | aoiThread.start();
84 | }
85 |
86 | private void addSamImage(SamImage samImage) {
87 | if (samImage.getEncode()) {
88 | listener.addLayer();
89 | listener.addBboxLayer(samImage.getBboxWay());
90 | listener.onAddSamImage(samImage);
91 | new Notification(tr("Added a sam image.")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
92 | } else {
93 | new Notification(tr("Error adding sam image.")).setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_SHORT).show();
94 | }
95 | }
96 |
97 | private LayerImageValues getLayeredImage(MapView mapView) {
98 | LayerImageValues layerImageValues = new LayerImageValues();
99 | BufferedImage bufImage = new BufferedImage(mapView.getWidth(), mapView.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
100 | Graphics2D imgGraphics = bufImage.createGraphics();
101 | imgGraphics.setClip(0, 0, mapView.getWidth(), mapView.getHeight());
102 |
103 | for (Layer layer : mapView.getLayerManager().getVisibleLayersInZOrder()) {
104 | if (layer.isVisible() && layer.isBackgroundLayer()) {
105 | Composite translucent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) layer.getOpacity());
106 | imgGraphics.setComposite(translucent);
107 | mapView.paintLayer(layer, imgGraphics);
108 | layerImageValues.setBufferedImage(bufImage);
109 | layerImageValues.setLayerName(layer.getName());
110 | }
111 |
112 | }
113 |
114 | return layerImageValues;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Ui/MagicWandDialog.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui;
2 |
3 | import org.locationtech.jts.geom.Coordinate;
4 | import org.locationtech.jts.geom.GeometryFactory;
5 | import org.locationtech.jts.geom.Point;
6 | import org.openstreetmap.josm.data.osm.DataSet;
7 | import org.openstreetmap.josm.data.osm.Node;
8 | import org.openstreetmap.josm.data.osm.Way;
9 | import org.openstreetmap.josm.gui.MainApplication;
10 | import org.openstreetmap.josm.gui.SideButton;
11 | import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
12 | import org.openstreetmap.josm.gui.layer.Layer;
13 | import org.openstreetmap.josm.gui.layer.OsmDataLayer;
14 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.MergeSelectAction;
15 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Actions.SimplifySelectAction;
16 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
17 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions.AutoAddTagAction;
18 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions.AutoSam;
19 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui.ButtonActions.SamEncondeAction;
20 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.*;
21 | import org.openstreetmap.josm.tools.Logging;
22 |
23 | import javax.swing.*;
24 | import javax.swing.border.Border;
25 | import javax.swing.border.TitledBorder;
26 | import java.awt.*;
27 | import java.awt.event.ActionEvent;
28 | import java.awt.event.ActionListener;
29 | import java.util.ArrayList;
30 | import java.util.Arrays;
31 | import java.util.EventListener;
32 |
33 | import static org.openstreetmap.josm.tools.I18n.tr;
34 |
35 | public class MagicWandDialog extends ToggleDialog implements ImageSamPanelListener {
36 | // variables
37 | private SamImageGrid samImageGrid;
38 | private final JPanel mainJpanel;
39 | private OsmDataLayer uneditableLayer = null;
40 | private final boolean canSamAoi = false;
41 |
42 | public MagicWandDialog() {
43 | super(tr("Magic Wand"), "magicwand-info.svg", tr("Open MagicWand windows"), null, 200, false);
44 |
45 | mainJpanel = new JPanel();
46 | mainJpanel.setLayout(new BoxLayout(mainJpanel, BoxLayout.Y_AXIS));
47 |
48 | JPanel optionPanel = new JPanel();
49 | optionPanel.setLayout(new GridLayout(6, 1, 3, 3));
50 | // tolerance
51 | optionPanel.add(buildTolerancePanel());
52 | // simplify
53 | optionPanel.add(buildPolygonHullPanel());
54 | optionPanel.add(buildDouglaspPanel());
55 | optionPanel.add(buildTopologyPreservingPanel());
56 | optionPanel.add(buildChaikinAnglePanel());
57 | optionPanel.add(buildSamParams());
58 | // add mainJpanel
59 | mainJpanel.add(optionPanel);
60 | // sam image
61 | mainJpanel.add(buildSamImagesPanel());
62 | // layer
63 | initLayer();
64 | // buttons
65 | // mege
66 | SideButton mergeGeometry = new SideButton(new MergeSelectAction(""));
67 | // simplify
68 | SideButton simplifyGeometry = new SideButton(new SimplifySelectAction(""));
69 | // sam
70 | SideButton autoSamButton = new SideButton(new AutoSam(this));
71 | // sam
72 | SideButton samButton = new SideButton(new SamEncondeAction(this));
73 |
74 | createLayout(mainJpanel, true, Arrays.asList(mergeGeometry, simplifyGeometry, autoSamButton, samButton));
75 | }
76 |
77 | private JPanel buildTolerancePanel() {
78 | JPanel jpanel = new JPanel();
79 | jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.Y_AXIS));
80 | jpanel.setPreferredSize(new Dimension(0, 25));
81 | int initValue = 9;
82 | TitledBorder titledBorder = BorderFactory.createTitledBorder("Tolerance: " + initValue);
83 | jpanel.setBorder(titledBorder);
84 | ToolSettings.setTolerance(initValue);
85 | //
86 | JSlider jSlider = new JSlider(1, 30, initValue);
87 | jSlider.setPaintTrack(true);
88 | jSlider.setPaintTicks(true);
89 | jSlider.setPaintLabels(true);
90 |
91 | jpanel.add(jSlider);
92 | jSlider.addChangeListener(changeEvent -> {
93 | JSlider source = (JSlider) changeEvent.getSource();
94 | int value = source.getValue();
95 | titledBorder.setTitle(tr("Tolerance: " + value));
96 | ToolSettings.setTolerance(value);
97 | jpanel.repaint();
98 | });
99 |
100 | return jpanel;
101 | }
102 |
103 | private JPanel buildPolygonHullPanel() {
104 | JPanel jpanel = new JPanel();
105 | jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.Y_AXIS));
106 | jpanel.setPreferredSize(new Dimension(0, 25));
107 | //
108 | double decimalPlaces = Math.pow(10, 3);
109 | double min = 0.5;
110 | int initValue = (int) (0.95 * decimalPlaces);
111 | //
112 | TitledBorder titledBorder = BorderFactory.createTitledBorder("Exterior contour: " + initValue / decimalPlaces);
113 | jpanel.setBorder(titledBorder);
114 |
115 | ToolSettings.setSimplPolygonHull(initValue / decimalPlaces);
116 | //
117 | JSlider jSlider = new JSlider((int) (min * decimalPlaces), (int) decimalPlaces, initValue);
118 | jSlider.setPaintTrack(true);
119 | jSlider.setPaintTicks(true);
120 | jSlider.setPaintLabels(true);
121 |
122 | jpanel.add(jSlider);
123 | jSlider.addChangeListener(changeEvent -> {
124 | JSlider source = (JSlider) changeEvent.getSource();
125 | double value = source.getValue();
126 | if (value <= (min * decimalPlaces)) {
127 | value = 0.0;
128 | } else {
129 | value /= decimalPlaces;
130 | }
131 |
132 | titledBorder.setTitle(tr("Exterior contour: " + value));
133 | ToolSettings.setSimplPolygonHull(value);
134 | jpanel.repaint();
135 | });
136 |
137 |
138 | return jpanel;
139 | }
140 |
141 | private JPanel buildDouglaspPanel() {
142 | JPanel jpanel = new JPanel();
143 | jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.Y_AXIS));
144 | //
145 | double decimalPlaces = Math.pow(10, 3);
146 | int initValue = 1000;
147 | //
148 | TitledBorder titledBorder = BorderFactory.createTitledBorder("Vertices: " + initValue / decimalPlaces);
149 | jpanel.setBorder(titledBorder);
150 | ToolSettings.setSimplDouglasP(initValue / decimalPlaces);
151 | //
152 | JSlider jSlider = new JSlider(0, (int) (5 * decimalPlaces), initValue);
153 | jSlider.setPaintTrack(true);
154 | jSlider.setPaintTicks(true);
155 | jSlider.setPaintLabels(true);
156 |
157 | jpanel.add(jSlider);
158 | jSlider.addChangeListener(changeEvent -> {
159 | JSlider source = (JSlider) changeEvent.getSource();
160 | double value = source.getValue() / decimalPlaces;
161 | titledBorder.setTitle(tr("Vertices: " + value));
162 | ToolSettings.setSimplDouglasP(value);
163 | jpanel.repaint();
164 | });
165 |
166 |
167 | return jpanel;
168 | }
169 |
170 | private JPanel buildTopologyPreservingPanel() {
171 | JPanel jpanel = new JPanel();
172 | jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.Y_AXIS));
173 | //
174 | double decimalPlaces = Math.pow(10, 3);
175 | int initValue = 1000;
176 | //
177 | TitledBorder titledBorder = BorderFactory.createTitledBorder("Topology: " + initValue / decimalPlaces);
178 | jpanel.setBorder(titledBorder);
179 | ToolSettings.setSimplTopologyPreserving(initValue / decimalPlaces);
180 | //
181 | JSlider jSlider = new JSlider(0, (int) (5 * decimalPlaces), initValue);
182 | jSlider.setPaintTrack(true);
183 | jSlider.setPaintTicks(true);
184 | jSlider.setPaintLabels(true);
185 |
186 | jpanel.add(jSlider);
187 | jSlider.addChangeListener(changeEvent -> {
188 | JSlider source = (JSlider) changeEvent.getSource();
189 | double value = source.getValue() / decimalPlaces;
190 | titledBorder.setTitle(tr("Topology: " + value));
191 | ToolSettings.setSimplTopologyPreserving(value);
192 | jpanel.repaint();
193 | });
194 |
195 | return jpanel;
196 | }
197 |
198 | private JPanel buildChaikinAnglePanel() {
199 | JPanel jpanel = new JPanel();
200 | jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.Y_AXIS));
201 | //
202 | int initValue = 110;
203 | double minValue = 20.0;
204 | //
205 | TitledBorder titledBorder = BorderFactory.createTitledBorder("Smooth Angle: " + initValue);
206 | jpanel.setBorder(titledBorder);
207 | ToolSettings.setChaikinSmooAngle(initValue);
208 | //
209 | JSlider jSlider = new JSlider((int) minValue, 170, initValue);
210 | jSlider.setPaintTrack(true);
211 | jSlider.setPaintTicks(true);
212 | jSlider.setPaintLabels(true);
213 |
214 | jpanel.add(jSlider);
215 | jSlider.addChangeListener(changeEvent -> {
216 | JSlider source = (JSlider) changeEvent.getSource();
217 | double value = source.getValue();
218 | if (value <= minValue) {
219 | value = 0.0;
220 | }
221 | titledBorder.setTitle(tr("Smooth Angle: " + value));
222 | ToolSettings.setChaikinSmooAngle(value);
223 | jpanel.repaint();
224 | });
225 |
226 |
227 | return jpanel;
228 | }
229 |
230 | private JPanel buildSamParams() {
231 | JPanel jpanel = new JPanel();
232 | jpanel.setLayout(new GridLayout(1, 2, 3, 3));
233 | //
234 | int initArea = 10;
235 | double initThreshold = 0.000002;
236 | //
237 | ToolSettings.setSimplAreaSam(initArea);
238 | ToolSettings.setSimplDistanceSam(initThreshold);
239 |
240 | //
241 | NumericField jTextInputArea = new NumericField(false);
242 | NumericField jTextInputThreshold = new NumericField(true);
243 | // colors
244 | jTextInputArea.setBorder(new TitledBorder("Min area simplify"));
245 | jTextInputThreshold.setBorder(new TitledBorder("Min distance simplify"));
246 | //
247 | jTextInputArea.setText(String.format("%d", initArea));
248 | jTextInputThreshold.setText(String.format("%.8f", initThreshold));
249 | //
250 |
251 | jTextInputArea.addPropertyChangeListener("text", e -> {
252 | try {
253 | double doubleValue = Double.parseDouble((String) e.getNewValue());
254 | ToolSettings.setSimplAreaSam((int) doubleValue);
255 | } catch (Exception ex) {
256 | Logging.error(ex.getMessage());
257 | }
258 | });
259 | jTextInputThreshold.addPropertyChangeListener("text", e -> {
260 | try {
261 | double doubleValue = Double.parseDouble((String) e.getNewValue());
262 | ToolSettings.setSimplDistanceSam(doubleValue);
263 | } catch (Exception ex) {
264 | Logging.error(ex.getMessage());
265 | }
266 | });
267 |
268 | // add
269 | jpanel.add(jTextInputArea);
270 | jpanel.add(jTextInputThreshold);
271 |
272 | return jpanel;
273 | }
274 |
275 | private JPanel buildSamImagesPanel() {
276 | samImageGrid = new SamImageGrid(150);
277 | samImageGrid.setLayout(new GridLayout(0, 2, 2, 3));
278 |
279 | return samImageGrid;
280 | }
281 |
282 | private void initLayer() {
283 | if (uneditableLayer == null || !MainApplication.getLayerManager().containsLayer(uneditableLayer)) {
284 | DataSet bboxDataset = new DataSet();
285 | uneditableLayer = new OsmDataLayer(bboxDataset, "Magic Wand Uneditable Layer", null);
286 | uneditableLayer.setUploadDiscouraged(false);
287 | }
288 | }
289 |
290 | @Override
291 | public void onAddSamImage(SamImage samImage) {
292 | samImageGrid.addSamImage(samImage);
293 | }
294 |
295 | @Override
296 | public void onRemoveAll() {
297 | samImageGrid.removeAllSamImage();
298 | }
299 |
300 | @Override
301 | public ArrayList getSamImageList() {
302 | return samImageGrid.getSamImageList();
303 | }
304 |
305 | @Override
306 | public SamImage getSamImageIncludepoint(double x, double y) {
307 | GeometryFactory geometryFactory = new GeometryFactory();
308 | Coordinate coordinate = new Coordinate(x, y);
309 | Point point = geometryFactory.createPoint(coordinate);
310 |
311 | return samImageGrid.getSamImageIncludepoint(point);
312 | }
313 |
314 | @Override
315 | public void addLayer() {
316 | try {
317 | initLayer();
318 |
319 | Layer activeLayer = MainApplication.getLayerManager().getActiveDataLayer();
320 | if (activeLayer == null) {
321 | activeLayer = new OsmDataLayer(new DataSet(), "Data Layer ", null);
322 | MainApplication.getLayerManager().addLayer(activeLayer);
323 | }
324 | int indexActiveLayer = MainApplication.getLayerManager().getLayers().indexOf(activeLayer);
325 |
326 | if (!MainApplication.getLayerManager().containsLayer(uneditableLayer)) {
327 | MainApplication.getLayerManager().addLayer(uneditableLayer);
328 | MainApplication.getLayerManager().setActiveLayer(activeLayer);
329 | }
330 | int indexUneditableLayer = MainApplication.getLayerManager().getLayers().indexOf(uneditableLayer);
331 |
332 | if (indexActiveLayer >= indexUneditableLayer) {
333 | MainApplication.getLayerManager().moveLayer(uneditableLayer, indexActiveLayer);
334 | }
335 | } catch (Exception e) {
336 | Logging.error(e);
337 | }
338 | }
339 |
340 | @Override
341 | public void addBboxLayer(Way way) {
342 | for (Node node : way.getNodes()) {
343 | if (!uneditableLayer.getDataSet().containsNode(node)) {
344 | uneditableLayer.getDataSet().addPrimitive(node);
345 | }
346 | }
347 | uneditableLayer.getDataSet().addPrimitive(way);
348 | }
349 |
350 | }
351 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/Ui/TagsDialog.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.Ui;
2 |
3 | import org.openstreetmap.josm.gui.ExtendedDialog;
4 | import org.openstreetmap.josm.gui.MainApplication;
5 | import org.openstreetmap.josm.gui.Notification;
6 | import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
7 | import org.openstreetmap.josm.plugins.devseed.JosmMagicWand.ToolSettings;
8 | import org.openstreetmap.josm.tools.GBC;
9 |
10 | import javax.swing.*;
11 | import java.awt.*;
12 |
13 | import static org.openstreetmap.josm.tools.I18n.tr;
14 |
15 | public class TagsDialog extends ExtendedDialog {
16 |
17 | private final HistoryComboBox addTags = new HistoryComboBox();
18 | private final JPanel mainPanel;
19 |
20 | public TagsDialog() {
21 | super(MainApplication.getMainFrame(), tr("Magic Wand Auto tags"), tr("Ok"), tr("Cancel"));
22 | setButtonIcons("ok", "cancel");
23 | setCancelButton(2);
24 | mainPanel = new JPanel(new GridBagLayout());
25 |
26 | mainPanel.add(new JLabel(" Auto add tags"
27 | + "
" + tr("Please add in the format: key=value")), GBC.eol().fill(GBC.HORIZONTAL));
28 |
29 | addTags.setEditable(true);
30 | addTags.getModel().prefs().load("magicwand.tags-history");
31 | addTags.setAutocompleteEnabled(true);
32 | mainPanel.add(addTags, GBC.eop().fill(GBC.HORIZONTAL));
33 |
34 | if (ToolSettings.getAutoTags() != null && !ToolSettings.getAutoTags().isEmpty()) {
35 | addTags.setText(ToolSettings.getAutoTags());
36 |
37 | }
38 |
39 | setContent(mainPanel, false);
40 | setupDialog();
41 | setVisible(true);
42 | }
43 |
44 | public void saveSettings() {
45 | if (addTags.getText().isEmpty()) {
46 | ToolSettings.setAutoTags("");
47 | return;
48 | }
49 | String regex = "^[a-zA-Z0-9]+=[a-zA-Z0-9]+$";
50 | if (addTags.getText().matches(regex)) {
51 | ToolSettings.setAutoTags(addTags.getText());
52 | addTags.addItem(addTags.getText());
53 | addTags.getModel().prefs().save("magicwand.tags-history");
54 | } else {
55 | new Notification(tr("Label is in the wrong format")).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/Constants.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | public class Constants {
4 | public static final String SAM_API = "https://samgeo-api.geocompas.ai";
5 | public static final String ENCODE = buildEndpoint("aoi");
6 | public static final String DECODE = buildEndpoint("segment_predictor");
7 | public static final String AUTOMATIC = buildEndpoint("segment_automatic");
8 |
9 | private static String buildEndpoint(String path) {
10 | return SAM_API +"/"+ path;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/CustomPolygon.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import org.locationtech.jts.geom.Polygon;
4 | import org.openstreetmap.josm.data.osm.Way;
5 | import org.openstreetmap.josm.tools.Logging;
6 |
7 | import java.util.UUID;
8 |
9 | public class CustomPolygon {
10 | private final String id;
11 | private Polygon pol;
12 | private boolean isUse;
13 | private Way way;
14 |
15 | public CustomPolygon() {
16 | this.id = UUID.randomUUID().toString();
17 | this.isUse = false;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "CustomPolygon [id=" + id + ", isUse=" + isUse + "]";
23 | }
24 |
25 | public void fromWay(Way w) {
26 | this.way = w;
27 | try {
28 | this.pol = CommonUtils.coordinates2Polygon(CommonUtils.nodes2Coordinates(w.getNodes()));
29 | } catch (Exception ex) {
30 | Logging.error(ex);
31 | }
32 | }
33 |
34 | public String id() {
35 | return id;
36 | }
37 |
38 | public Polygon polygon() {
39 | return pol;
40 | }
41 |
42 | public boolean isEmpty() {
43 | return pol.isEmpty();
44 | }
45 |
46 | public Way way() {
47 | return way;
48 | }
49 |
50 | public boolean isUse() {
51 | return isUse;
52 | }
53 |
54 | public void usePolygon() {
55 | this.isUse = true;
56 | }
57 |
58 | public void setPol(Polygon pol) {
59 | this.pol = pol;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/FloodFillFacade.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import org.opencv.core.Mat;
4 | import org.opencv.core.Point;
5 | import org.opencv.core.Rect;
6 | import org.opencv.core.Scalar;
7 | import org.opencv.imgproc.Imgproc;
8 | import org.openstreetmap.josm.tools.Logging;
9 |
10 | import java.util.Random;
11 |
12 | public class FloodFillFacade {
13 |
14 | public static final int FIXED_RANGE = 1;
15 | private final Random random = new Random();
16 | private final int newMaskVal = 255;
17 | private boolean colored = true;
18 | private boolean masked = true;
19 | private int range = FIXED_RANGE;
20 | private int connectivity = 8;
21 | private int lowerDiff = 7;
22 | private int upperDiff = 9;
23 |
24 |
25 | @Override
26 | public String toString() {
27 | return "FloodFillFacade [colored=" + colored + ", masked=" + masked + ", range=" + range + ", random=" + random + ", connectivity=" + connectivity + ", newMaskVal=" + newMaskVal + ", lowerDiff=" + lowerDiff + ", upperDiff=" + upperDiff + "]";
28 | }
29 |
30 |
31 | public void fill(Mat image, Mat mask, int x, int y) {
32 | Point seedPoint = new Point(x, y);
33 |
34 | int b = random.nextInt(256);
35 | int g = random.nextInt(256);
36 | int r = random.nextInt(256);
37 | Rect rect = new Rect();
38 |
39 | Scalar newVal = isColored() ? new Scalar(b, g, r) : new Scalar(r * 0.299 + g * 0.587 + b * 0.114);
40 |
41 | Scalar lowerDifference = new Scalar(lowerDiff, lowerDiff, lowerDiff);
42 | Scalar upperDifference = new Scalar(upperDiff, upperDiff, upperDiff);
43 | Logging.info("lowerDiff " + lowerDiff + " upperDiff " + upperDiff + " connectivity " + connectivity);
44 | int flags = connectivity + (newMaskVal << 8) + (range == FIXED_RANGE ? Imgproc.FLOODFILL_FIXED_RANGE : 0);
45 | //Imgproc.FLOODFILL_MASK_ONLY);
46 | Imgproc.floodFill(image, mask, seedPoint, newVal, rect, lowerDifference, upperDifference, flags);
47 | }
48 |
49 |
50 | public int getConnectivity() {
51 | return connectivity;
52 | }
53 |
54 | public void setConnectivity(int connectivity) {
55 | this.connectivity = connectivity;
56 | }
57 |
58 | public boolean isColored() {
59 | return colored;
60 | }
61 |
62 | public void setColored(boolean colored) {
63 | this.colored = colored;
64 | }
65 |
66 | public boolean isMasked() {
67 | return masked;
68 | }
69 |
70 | public void setMasked(boolean masked) {
71 | this.masked = masked;
72 | }
73 |
74 | public int getRange() {
75 | return range;
76 | }
77 |
78 | public void setRange(int range) {
79 | this.range = range;
80 | }
81 |
82 |
83 | public int getLowerDiff() {
84 | return lowerDiff;
85 | }
86 |
87 | public void setLowerDiff(int lowerDiff) {
88 | this.lowerDiff = lowerDiff;
89 | }
90 |
91 | public int getUpperDiff() {
92 | return upperDiff;
93 | }
94 |
95 | public void setUpperDiff(int upperDiff) {
96 | this.upperDiff = upperDiff;
97 | }
98 |
99 | public void setTolerance(int tolerance) {
100 | this.lowerDiff = tolerance;
101 | this.upperDiff = tolerance + 2;
102 | }
103 | }
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/ImagePanel.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import org.openstreetmap.josm.data.ProjectionBounds;
4 | import org.openstreetmap.josm.data.imagery.ImageryInfo;
5 | import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
6 | import org.openstreetmap.josm.gui.MapView;
7 | import org.openstreetmap.josm.gui.layer.ImageryLayer;
8 | import org.openstreetmap.josm.gui.layer.Layer;
9 | import org.openstreetmap.josm.tools.ImageProvider;
10 | import org.openstreetmap.josm.tools.Logging;
11 |
12 | import javax.swing.*;
13 | import java.awt.*;
14 | import java.awt.image.BufferedImage;
15 | import java.util.List;
16 | import java.util.stream.Collectors;
17 |
18 | import static org.openstreetmap.josm.gui.MainApplication.getMap;
19 |
20 |
21 | public class ImagePanel extends JPanel {
22 |
23 | private final BufferedImage image;
24 | private JButton zoomJButton;
25 | private JButton deleteJButton;
26 | private final int maxHeight;
27 | private final int maxWidth;
28 |
29 | private final SamImage samImage;
30 |
31 | private final JLabel imageLabel;
32 | private final ImagePanelListener listener;
33 |
34 | public ImagePanel(SamImage samImage, int maxWidth, ImagePanelListener listener) {
35 | setLayout(null);
36 | this.samImage = samImage;
37 | this.image = samImage.getLayerImage();
38 | this.maxWidth = maxWidth;
39 |
40 | this.maxHeight = getMaxHeight(samImage.getLayerImage(), maxWidth);
41 | this.listener = listener;
42 | setupButtons();
43 | // image
44 | Graphics2D g2d = this.image.createGraphics();
45 | g2d.dispose();
46 | ImageIcon icono = new ImageIcon(getScaledImage(this.image, maxWidth, this.maxHeight));
47 | imageLabel = new JLabel(icono);
48 | add(imageLabel);
49 | imageLabel.setBounds(0, 0, this.maxWidth, this.maxHeight);
50 | setPreferredSize(new Dimension(this.maxWidth, this.maxHeight));
51 | // setup actions
52 |
53 | }
54 |
55 | private Image getScaledImage(BufferedImage originalImage, int maxWidth, int maxHeight) {
56 | int width = originalImage.getWidth();
57 |
58 | if (width <= maxWidth) {
59 | return originalImage;
60 | }
61 |
62 | return originalImage.getScaledInstance(maxWidth, maxHeight, Image.SCALE_SMOOTH);
63 | }
64 |
65 | private int getMaxHeight(BufferedImage originalImage, int maxWidth) {
66 | int width = originalImage.getWidth();
67 | int height = originalImage.getHeight();
68 |
69 | double radio = (double) width / height;
70 |
71 | if (width <= maxWidth) {
72 | return height;
73 | }
74 | return (int) (maxWidth / radio);
75 |
76 | }
77 |
78 | private void setupButtons() {
79 | //
80 | ImageIcon zoomIco = new ImageProvider("dialogs", "zoom-best-fit").get();
81 | ImageIcon deleteIco = new ImageProvider("dialogs", "delete").get();
82 |
83 | zoomJButton = new JButton(zoomIco);
84 |
85 | zoomJButton.setBounds(20, this.maxHeight - 32, zoomIco.getIconWidth(), zoomIco.getIconHeight());
86 | zoomJButton.setContentAreaFilled(false);
87 | zoomJButton.addActionListener(e -> zoomAction());
88 | add(zoomJButton);
89 |
90 | deleteJButton = new JButton(deleteIco);
91 | deleteJButton.setBounds(70, this.maxHeight - 32, deleteIco.getIconWidth(), deleteIco.getIconHeight());
92 | deleteJButton.setContentAreaFilled(false);
93 | deleteJButton.addActionListener(e -> deleteAction());
94 |
95 | add(deleteJButton);
96 |
97 | }
98 |
99 | private void zoomAction() {
100 | MapView mapView = getMap().mapView;
101 |
102 | try {
103 | // add layer
104 | List activeLayers = mapView.getLayerManager()
105 | .getVisibleLayersInZOrder()
106 | .stream()
107 | .filter(layer -> (layer instanceof ImageryLayer && layer.isVisible() && layer.getName().equals(samImage.getLayerName())))
108 | .collect(Collectors.toList());
109 |
110 | if (activeLayers.isEmpty()) {
111 | List imagerySources = ImageryLayerInfo
112 | .instance
113 | .getLayers()
114 | .stream()
115 | .filter(layer -> (layer.getName().equals(samImage.getLayerName())))
116 | .collect(Collectors.toList());
117 |
118 | if (!imagerySources.isEmpty()) {
119 | ImageryInfo imageryInfo = imagerySources.get(0);
120 | mapView.getLayerManager().addLayer(ImageryLayer.create(imageryInfo));
121 | }
122 | }
123 | } catch (Exception e) {
124 | Logging.error(e);
125 | }
126 |
127 | ProjectionBounds projectionBounds = samImage.getProjectionBounds();
128 | mapView.zoomTo(projectionBounds);
129 | mapView.zoomIn();
130 | mapView.repaint();
131 | }
132 |
133 | private void deleteAction() {
134 | try {
135 | samImage.removeCacheImge();
136 | listener.removeSamImage(samImage);
137 | } catch (Exception e) {
138 | Logging.error(e);
139 | }
140 | }
141 | }
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/ImagePanelListener.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | public interface ImagePanelListener {
4 | void removeSamImage(SamImage samImage);
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/ImageSamPanelListener.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 |
4 | import org.openstreetmap.josm.data.osm.Way;
5 |
6 | import java.util.ArrayList;
7 |
8 | public interface ImageSamPanelListener {
9 | void onAddSamImage(SamImage samImage);
10 |
11 | void onRemoveAll();
12 |
13 | ArrayList getSamImageList();
14 |
15 | SamImage getSamImageIncludepoint(double x, double y);
16 |
17 | void addLayer();
18 |
19 | void addBboxLayer(Way way);
20 |
21 | }
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/LayerImageValues.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import java.awt.image.BufferedImage;
4 |
5 | public class LayerImageValues {
6 | BufferedImage bufferedImage;
7 | String layerName;
8 |
9 | public LayerImageValues() {
10 | }
11 |
12 | public BufferedImage getBufferedImage() {
13 | return bufferedImage;
14 | }
15 |
16 | public void setBufferedImage(BufferedImage bufferedImage) {
17 | this.bufferedImage = bufferedImage;
18 | }
19 |
20 | public String getLayerName() {
21 | return layerName;
22 | }
23 |
24 | public void setLayerName(String layerName) {
25 | this.layerName = layerName;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/NumericField.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import javax.swing.*;
4 | import javax.swing.text.DocumentFilter;
5 | import javax.swing.text.AttributeSet;
6 | import javax.swing.text.BadLocationException;
7 | import javax.swing.text.PlainDocument;
8 |
9 | public class NumericField extends JTextField {
10 | public NumericField(boolean allowDecimal) {
11 | super();
12 | ((PlainDocument) this.getDocument()).setDocumentFilter(new DocumentFilter() {
13 | @Override
14 | public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
15 | if (validateInput(string, allowDecimal)) {
16 | super.insertString(fb, offset, string, attr);
17 | firePropertyChange("text", "", getText());
18 | }
19 | }
20 |
21 | @Override
22 | public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
23 | if (validateInput(text, allowDecimal)) {
24 | super.replace(fb, offset, length, text, attrs);
25 | firePropertyChange("text", "", getText());
26 | }
27 | }
28 |
29 | private boolean validateInput(String text, boolean allowDecimal) {
30 | if (allowDecimal) {
31 | return text.matches("^\\d+(\\.\\d+)?$");
32 | } else {
33 | return text.matches("\\d*");
34 | }
35 | }
36 | });
37 | }
38 | }
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/SamImageGrid.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.locationtech.jts.geom.Point;
5 | import org.openstreetmap.josm.tools.Logging;
6 |
7 | import javax.swing.*;
8 | import java.awt.*;
9 | import java.io.File;
10 | import java.time.LocalDateTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.Comparator;
15 |
16 | public class SamImageGrid extends JPanel implements ImagePanelListener {
17 | ObjectMapper objectMapper = new ObjectMapper();
18 | private final ArrayList samImageList;
19 | private final int maxWidth;
20 |
21 | public SamImageGrid(int maxWidth) {
22 | this.maxWidth = maxWidth;
23 | samImageList = new ArrayList<>();
24 | setLayout(new GridLayout(0, 2, 1, 1));
25 |
26 | //
27 | File cacheDir = new File(CommonUtils.magicWandCacheDirPath());
28 | File[] cacheFiles = cacheDir.listFiles((dir, fileName) -> fileName.endsWith(".json"));
29 | if (cacheFiles != null) {
30 | Arrays.sort(cacheFiles, new Comparator() {
31 | @Override
32 | public int compare(File file1, File file2) {
33 | LocalDateTime dateTime1 = extractDateTimeFromFileName(file1.getName());
34 | LocalDateTime dateTime2 = extractDateTimeFromFileName(file2.getName());
35 | return dateTime1.compareTo(dateTime2);
36 | }
37 | });
38 | }
39 |
40 |
41 | for (File jsonFile : cacheFiles) {
42 | try {
43 | SamImage samImage = objectMapper.readValue(jsonFile, SamImage.class);
44 | addSamImage(samImage);
45 | } catch (Exception e) {
46 | Logging.error(e);
47 | }
48 | }
49 | }
50 |
51 | public void addSamImage(SamImage samImage) {
52 | if (samImage.getEncode() && !samImage.getImageUrl().isEmpty()) {
53 | samImageList.add(0, samImage);
54 | }
55 | updateJpanel();
56 | }
57 |
58 | public void removeAllSamImage() {
59 | samImageList.clear();
60 | updateJpanel();
61 | }
62 |
63 | public ArrayList getSamImageList() {
64 | return samImageList;
65 | }
66 |
67 | public SamImage getSamImageIncludepoint(Point p) {
68 | for (SamImage s : samImageList) {
69 | if (s.containsPoint(p)) {
70 | return s;
71 | }
72 | }
73 | return null;
74 | }
75 |
76 | private void updateJpanel() {
77 | removeAll();
78 | for (SamImage samImage : samImageList) {
79 | add(new ImagePanel(samImage, this.maxWidth, this));
80 | }
81 | revalidate();
82 | repaint();
83 | }
84 |
85 | private LocalDateTime extractDateTimeFromFileName(String fileName) {
86 | try {
87 | // '2024_10_07__12_17_22__farm.json'
88 | String[] parts = fileName.split("__");
89 | String datePart = parts[0]; // '2024_10_07'
90 | String timePart = parts[1]; // '12_17_22'
91 |
92 | String dateTimeString = datePart + " " + timePart;
93 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd HH_mm_ss");
94 |
95 | return LocalDateTime.parse(dateTimeString, formatter);
96 | } catch (Exception e) {
97 | Logging.error("Error parsing date from file name: " + fileName);
98 | return LocalDateTime.MIN;
99 | }
100 | }
101 |
102 | @Override
103 | public void removeSamImage(SamImage samImage) {
104 | try {
105 | samImageList.remove(samImage);
106 | updateJpanel();
107 | } catch (Exception e) {
108 | Logging.error(e);
109 |
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/samDto/DecodeRequestBody.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.samDto;
2 |
3 | import java.util.List;
4 |
5 | public class DecodeRequestBody {
6 | private String action_type;
7 | private List bbox;
8 | private String crs;
9 | private String id;
10 | private List> point_coords;
11 | private List point_labels;
12 | private String project;
13 | private Integer zoom;
14 | private String return_format;
15 | private double simplify_tolerance;
16 | private int area_val;
17 |
18 | public DecodeRequestBody(String action_type, List bbox, String id, List> point_coords, List point_labels, String project, Integer zoom) {
19 | this.action_type = action_type;
20 | this.bbox = bbox;
21 | this.crs = "EPSG:4326";
22 | this.id = id;
23 | this.point_coords = point_coords;
24 | this.point_labels = point_labels;
25 | this.project = project;
26 | this.zoom = zoom;
27 | this.return_format = "geojson";
28 | this.simplify_tolerance = 0.000002;
29 | this.area_val = 15;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "DecodeRequestBody{" +
35 | "action_type='" + action_type + '\'' +
36 | ", bbox=" + bbox +
37 | ", crs='" + crs + '\'' +
38 | ", id='" + id + '\'' +
39 | ", point_coords=" + point_coords +
40 | ", point_labels=" + point_labels +
41 | ", project='" + project + '\'' +
42 | ", zoom=" + zoom +
43 | '}';
44 | }
45 |
46 | public String getAction_type() {
47 | return action_type;
48 | }
49 |
50 | public void setAction_type(String action_type) {
51 | this.action_type = action_type;
52 | }
53 |
54 | public List getBbox() {
55 | return bbox;
56 | }
57 |
58 | public void setBbox(List bbox) {
59 | this.bbox = bbox;
60 | }
61 |
62 | public String getCrs() {
63 | return crs;
64 | }
65 |
66 | public void setCrs(String crs) {
67 | this.crs = crs;
68 | }
69 |
70 | public String getId() {
71 | return id;
72 | }
73 |
74 | public void setId(String id) {
75 | this.id = id;
76 | }
77 |
78 | public List> getPoint_coords() {
79 | return point_coords;
80 | }
81 |
82 | public void setPoint_coords(List> point_coords) {
83 | this.point_coords = point_coords;
84 | }
85 |
86 | public List getPoint_labels() {
87 | return point_labels;
88 | }
89 |
90 | public void setPoint_labels(List point_labels) {
91 | this.point_labels = point_labels;
92 | }
93 |
94 | public String getProject() {
95 | return project;
96 | }
97 |
98 | public void setProject(String project) {
99 | this.project = project;
100 | }
101 |
102 | public Integer getZoom() {
103 | return zoom;
104 | }
105 |
106 | public void setZoom(Integer zoom) {
107 | this.zoom = zoom;
108 | }
109 |
110 | public String getReturn_format() {
111 | return return_format;
112 | }
113 |
114 | public void setReturn_format(String return_format) {
115 | this.return_format = return_format;
116 | }
117 |
118 | public int getArea_val() {
119 | return area_val;
120 | }
121 |
122 | public void setArea_val(int area_val) {
123 | this.area_val = area_val;
124 | }
125 |
126 | public double getSimplify_tolerance() {
127 | return simplify_tolerance;
128 | }
129 |
130 | public void setSimplify_tolerance(double simplify_tolerance) {
131 | this.simplify_tolerance = simplify_tolerance;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/samDto/EncodeResponse.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.samDto;
2 |
3 | public class EncodeResponse {
4 | private String project;
5 | private String id;
6 | private double[] bbox;
7 | private int zoom;
8 | private String imageUrl;
9 | private String tifUrl;
10 | private String return_format;
11 |
12 | public EncodeResponse() {
13 | }
14 |
15 | public EncodeResponse(String project, String id, double[] bbox, int zoom, String imageUrl, String tifUrl, String return_format) {
16 | this.project = project;
17 | this.id = id;
18 | this.bbox = bbox;
19 | this.zoom = zoom;
20 | this.imageUrl = imageUrl;
21 | this.tifUrl = tifUrl;
22 | this.return_format = return_format;
23 | }
24 |
25 | // Getters y Setters
26 | public String getProject() {
27 | return project;
28 | }
29 |
30 | public void setProject(String project) {
31 | this.project = project;
32 | }
33 |
34 | public String getId() {
35 | return id;
36 | }
37 |
38 | public void setId(String id) {
39 | this.id = id;
40 | }
41 |
42 | public double[] getBbox() {
43 | return bbox;
44 | }
45 |
46 | public void setBbox(double[] bbox) {
47 | this.bbox = bbox;
48 | }
49 |
50 | public int getZoom() {
51 | return zoom;
52 | }
53 |
54 | public void setZoom(int zoom) {
55 | this.zoom = zoom;
56 | }
57 |
58 | public String getImageUrl() {
59 | return imageUrl;
60 | }
61 |
62 | public void setImageUrl(String imageUrl) {
63 | this.imageUrl = imageUrl;
64 | }
65 |
66 | public String getTifUrl() {
67 | return tifUrl;
68 | }
69 |
70 | public void setTifUrl(String tifUrl) {
71 | this.tifUrl = tifUrl;
72 | }
73 |
74 | public String getReturn_format() {
75 | return return_format;
76 | }
77 |
78 | public void setReturn_format(String return_format) {
79 | this.return_format = return_format;
80 | }
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/src/org/openstreetmap/josm/plugins/devseed/JosmMagicWand/utils/samDto/EncondeRequestBody.java:
--------------------------------------------------------------------------------
1 | package org.openstreetmap.josm.plugins.devseed.JosmMagicWand.utils.samDto;
2 |
3 | import java.util.List;
4 |
5 | public class EncondeRequestBody {
6 | private String canvas_image;
7 | private String crs;
8 | private String id;
9 | private String project;
10 | private Integer zoom;
11 | private List bbox;
12 | private String return_format;
13 | private double simplify_tolerance;
14 | private int area_val;
15 |
16 | public EncondeRequestBody(String canvas_image, String project, Integer zoom, List bbox, String id, int area_val, double simplify_tolerance) {
17 | this.canvas_image = canvas_image;
18 | this.crs = "EPSG:4326";
19 | this.id = id;
20 | this.project = project;
21 | this.zoom = zoom;
22 | this.bbox = bbox;
23 | this.return_format = "geojson";
24 | this.area_val = area_val;
25 | this.simplify_tolerance = simplify_tolerance;
26 |
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return "EncondeRequestBody{" +
32 | "bbox=" + bbox +
33 | ", canvas_image='" + canvas_image + '\'' +
34 | ", crs='" + crs + '\'' +
35 | ", id='" + id + '\'' +
36 | ", project='" + project + '\'' +
37 | ", zoom=" + zoom +
38 | '}';
39 | }
40 |
41 | public Integer getZoom() {
42 | return zoom;
43 | }
44 |
45 | public void setZoom(Integer zoom) {
46 | this.zoom = zoom;
47 | }
48 |
49 | public String getProject() {
50 | return project;
51 | }
52 |
53 | public void setProject(String project) {
54 | this.project = project;
55 | }
56 |
57 | public String getId() {
58 | return id;
59 | }
60 |
61 | public void setId(String id) {
62 | this.id = id;
63 | }
64 |
65 | public String getCrs() {
66 | return crs;
67 | }
68 |
69 | public void setCrs(String crs) {
70 | this.crs = crs;
71 | }
72 |
73 | public String getCanvas_image() {
74 | return canvas_image;
75 | }
76 |
77 | public void setCanvas_image(String canvas_image) {
78 | this.canvas_image = canvas_image;
79 | }
80 |
81 | public List getBbox() {
82 | return bbox;
83 | }
84 |
85 | public void setBbox(List bbox) {
86 | this.bbox = bbox;
87 | }
88 |
89 | public String getReturn_format() {
90 | return return_format;
91 | }
92 |
93 | public void setReturn_format(String return_format) {
94 | this.return_format = return_format;
95 | }
96 |
97 | public int getArea_val() {
98 | return area_val;
99 | }
100 |
101 | public void setArea_val(int area_val) {
102 | this.area_val = area_val;
103 | }
104 |
105 | public double getSimplify_tolerance() {
106 | return simplify_tolerance;
107 | }
108 |
109 | public void setSimplify_tolerance(double simplify_tolerance) {
110 | this.simplify_tolerance = simplify_tolerance;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------